commit
e3f1c25c8a
|
@ -0,0 +1,308 @@
|
||||||
|
{
|
||||||
|
"always-semicolon": true,
|
||||||
|
"block-indent": 2,
|
||||||
|
"color-case": "lower",
|
||||||
|
"color-shorthand": true,
|
||||||
|
"element-case": "lower",
|
||||||
|
"eof-newline": true,
|
||||||
|
"leading-zero": false,
|
||||||
|
"remove-empty-rulesets": true,
|
||||||
|
"space-after-colon": 1,
|
||||||
|
"space-after-combinator": 1,
|
||||||
|
"space-before-selector-delimiter": 0,
|
||||||
|
"space-between-declarations": "\n",
|
||||||
|
"space-after-opening-brace": "\n",
|
||||||
|
"space-before-closing-brace": "\n",
|
||||||
|
"space-before-colon": 0,
|
||||||
|
"space-before-combinator": 1,
|
||||||
|
"space-before-opening-brace": 1,
|
||||||
|
"strip-spaces": true,
|
||||||
|
"unitless-zero": true,
|
||||||
|
"vendor-prefix-align": true,
|
||||||
|
"sort-order": [
|
||||||
|
[
|
||||||
|
"$variable",
|
||||||
|
"$extend",
|
||||||
|
"$include",
|
||||||
|
"position",
|
||||||
|
"top",
|
||||||
|
"right",
|
||||||
|
"bottom",
|
||||||
|
"left",
|
||||||
|
"z-index",
|
||||||
|
"-webkit-box-sizing",
|
||||||
|
"-moz-box-sizing",
|
||||||
|
"box-sizing",
|
||||||
|
"display",
|
||||||
|
"float",
|
||||||
|
"width",
|
||||||
|
"min-width",
|
||||||
|
"max-width",
|
||||||
|
"height",
|
||||||
|
"min-height",
|
||||||
|
"max-height",
|
||||||
|
"flex",
|
||||||
|
"flex-direction",
|
||||||
|
"flex-flow",
|
||||||
|
"flex-order",
|
||||||
|
"flex-pack",
|
||||||
|
"flex-align",
|
||||||
|
"padding",
|
||||||
|
"padding-top",
|
||||||
|
"padding-right",
|
||||||
|
"padding-bottom",
|
||||||
|
"padding-left",
|
||||||
|
"margin",
|
||||||
|
"margin-top",
|
||||||
|
"margin-right",
|
||||||
|
"margin-bottom",
|
||||||
|
"margin-left",
|
||||||
|
"overflow",
|
||||||
|
"overflow-x",
|
||||||
|
"overflow-y",
|
||||||
|
"-webkit-overflow-scrolling",
|
||||||
|
"-ms-overflow-x",
|
||||||
|
"-ms-overflow-y",
|
||||||
|
"-ms-overflow-style",
|
||||||
|
"clip",
|
||||||
|
"clear",
|
||||||
|
"font",
|
||||||
|
"font-family",
|
||||||
|
"font-size",
|
||||||
|
"font-style",
|
||||||
|
"font-weight",
|
||||||
|
"font-variant",
|
||||||
|
"font-size-adjust",
|
||||||
|
"font-stretch",
|
||||||
|
"font-effect",
|
||||||
|
"font-emphasize",
|
||||||
|
"font-emphasize-position",
|
||||||
|
"font-emphasize-style",
|
||||||
|
"font-smooth",
|
||||||
|
"-webkit-hyphens",
|
||||||
|
"-moz-hyphens",
|
||||||
|
"hyphens",
|
||||||
|
"line-height",
|
||||||
|
"color",
|
||||||
|
"text-align",
|
||||||
|
"-webkit-text-align-last",
|
||||||
|
"-moz-text-align-last",
|
||||||
|
"-ms-text-align-last",
|
||||||
|
"text-align-last",
|
||||||
|
"text-emphasis",
|
||||||
|
"text-emphasis-color",
|
||||||
|
"text-emphasis-style",
|
||||||
|
"text-emphasis-position",
|
||||||
|
"text-decoration",
|
||||||
|
"text-indent",
|
||||||
|
"text-justify",
|
||||||
|
"text-outline",
|
||||||
|
"-ms-text-overflow",
|
||||||
|
"text-overflow",
|
||||||
|
"text-overflow-ellipsis",
|
||||||
|
"text-overflow-mode",
|
||||||
|
"text-shadow",
|
||||||
|
"text-transform",
|
||||||
|
"text-wrap",
|
||||||
|
"-webkit-text-size-adjust",
|
||||||
|
"-ms-text-size-adjust",
|
||||||
|
"letter-spacing",
|
||||||
|
"-ms-word-break",
|
||||||
|
"word-break",
|
||||||
|
"word-spacing",
|
||||||
|
"-ms-word-wrap",
|
||||||
|
"word-wrap",
|
||||||
|
"-moz-tab-size",
|
||||||
|
"-o-tab-size",
|
||||||
|
"tab-size",
|
||||||
|
"white-space",
|
||||||
|
"vertical-align",
|
||||||
|
"list-style",
|
||||||
|
"list-style-position",
|
||||||
|
"list-style-type",
|
||||||
|
"list-style-image",
|
||||||
|
"pointer-events",
|
||||||
|
"-ms-touch-action",
|
||||||
|
"touch-action",
|
||||||
|
"cursor",
|
||||||
|
"visibility",
|
||||||
|
"zoom",
|
||||||
|
"table-layout",
|
||||||
|
"empty-cells",
|
||||||
|
"caption-side",
|
||||||
|
"border-spacing",
|
||||||
|
"border-collapse",
|
||||||
|
"content",
|
||||||
|
"quotes",
|
||||||
|
"counter-reset",
|
||||||
|
"counter-increment",
|
||||||
|
"resize",
|
||||||
|
"-webkit-user-select",
|
||||||
|
"-moz-user-select",
|
||||||
|
"-ms-user-select",
|
||||||
|
"-o-user-select",
|
||||||
|
"user-select",
|
||||||
|
"nav-index",
|
||||||
|
"nav-up",
|
||||||
|
"nav-right",
|
||||||
|
"nav-down",
|
||||||
|
"nav-left",
|
||||||
|
"background",
|
||||||
|
"background-color",
|
||||||
|
"background-image",
|
||||||
|
"-ms-filter:\\'progid:DXImageTransform.Microsoft.gradient",
|
||||||
|
"filter:progid:DXImageTransform.Microsoft.gradient",
|
||||||
|
"filter:progid:DXImageTransform.Microsoft.AlphaImageLoader",
|
||||||
|
"filter",
|
||||||
|
"background-repeat",
|
||||||
|
"background-attachment",
|
||||||
|
"background-position",
|
||||||
|
"background-position-x",
|
||||||
|
"background-position-y",
|
||||||
|
"-webkit-background-clip",
|
||||||
|
"-moz-background-clip",
|
||||||
|
"background-clip",
|
||||||
|
"background-origin",
|
||||||
|
"-webkit-background-size",
|
||||||
|
"-moz-background-size",
|
||||||
|
"-o-background-size",
|
||||||
|
"background-size",
|
||||||
|
"border",
|
||||||
|
"border-color",
|
||||||
|
"border-style",
|
||||||
|
"border-width",
|
||||||
|
"border-top",
|
||||||
|
"border-top-color",
|
||||||
|
"border-top-style",
|
||||||
|
"border-top-width",
|
||||||
|
"border-right",
|
||||||
|
"border-right-color",
|
||||||
|
"border-right-style",
|
||||||
|
"border-right-width",
|
||||||
|
"border-bottom",
|
||||||
|
"border-bottom-color",
|
||||||
|
"border-bottom-style",
|
||||||
|
"border-bottom-width",
|
||||||
|
"border-left",
|
||||||
|
"border-left-color",
|
||||||
|
"border-left-style",
|
||||||
|
"border-left-width",
|
||||||
|
"border-radius",
|
||||||
|
"border-top-left-radius",
|
||||||
|
"border-top-right-radius",
|
||||||
|
"border-bottom-right-radius",
|
||||||
|
"border-bottom-left-radius",
|
||||||
|
"-webkit-border-image",
|
||||||
|
"-moz-border-image",
|
||||||
|
"-o-border-image",
|
||||||
|
"border-image",
|
||||||
|
"-webkit-border-image-source",
|
||||||
|
"-moz-border-image-source",
|
||||||
|
"-o-border-image-source",
|
||||||
|
"border-image-source",
|
||||||
|
"-webkit-border-image-slice",
|
||||||
|
"-moz-border-image-slice",
|
||||||
|
"-o-border-image-slice",
|
||||||
|
"border-image-slice",
|
||||||
|
"-webkit-border-image-width",
|
||||||
|
"-moz-border-image-width",
|
||||||
|
"-o-border-image-width",
|
||||||
|
"border-image-width",
|
||||||
|
"-webkit-border-image-outset",
|
||||||
|
"-moz-border-image-outset",
|
||||||
|
"-o-border-image-outset",
|
||||||
|
"border-image-outset",
|
||||||
|
"-webkit-border-image-repeat",
|
||||||
|
"-moz-border-image-repeat",
|
||||||
|
"-o-border-image-repeat",
|
||||||
|
"border-image-repeat",
|
||||||
|
"outline",
|
||||||
|
"outline-width",
|
||||||
|
"outline-style",
|
||||||
|
"outline-color",
|
||||||
|
"outline-offset",
|
||||||
|
"-webkit-box-shadow",
|
||||||
|
"-moz-box-shadow",
|
||||||
|
"box-shadow",
|
||||||
|
"filter:progid:DXImageTransform.Microsoft.Alpha(Opacity",
|
||||||
|
"-ms-filter:\\'progid:DXImageTransform.Microsoft.Alpha",
|
||||||
|
"opacity",
|
||||||
|
"-ms-interpolation-mode",
|
||||||
|
"-webkit-transition",
|
||||||
|
"-moz-transition",
|
||||||
|
"-ms-transition",
|
||||||
|
"-o-transition",
|
||||||
|
"transition",
|
||||||
|
"-webkit-transition-delay",
|
||||||
|
"-moz-transition-delay",
|
||||||
|
"-ms-transition-delay",
|
||||||
|
"-o-transition-delay",
|
||||||
|
"transition-delay",
|
||||||
|
"-webkit-transition-timing-function",
|
||||||
|
"-moz-transition-timing-function",
|
||||||
|
"-ms-transition-timing-function",
|
||||||
|
"-o-transition-timing-function",
|
||||||
|
"transition-timing-function",
|
||||||
|
"-webkit-transition-duration",
|
||||||
|
"-moz-transition-duration",
|
||||||
|
"-ms-transition-duration",
|
||||||
|
"-o-transition-duration",
|
||||||
|
"transition-duration",
|
||||||
|
"-webkit-transition-property",
|
||||||
|
"-moz-transition-property",
|
||||||
|
"-ms-transition-property",
|
||||||
|
"-o-transition-property",
|
||||||
|
"transition-property",
|
||||||
|
"-webkit-transform",
|
||||||
|
"-moz-transform",
|
||||||
|
"-ms-transform",
|
||||||
|
"-o-transform",
|
||||||
|
"transform",
|
||||||
|
"-webkit-transform-origin",
|
||||||
|
"-moz-transform-origin",
|
||||||
|
"-ms-transform-origin",
|
||||||
|
"-o-transform-origin",
|
||||||
|
"transform-origin",
|
||||||
|
"-webkit-animation",
|
||||||
|
"-moz-animation",
|
||||||
|
"-ms-animation",
|
||||||
|
"-o-animation",
|
||||||
|
"animation",
|
||||||
|
"-webkit-animation-name",
|
||||||
|
"-moz-animation-name",
|
||||||
|
"-ms-animation-name",
|
||||||
|
"-o-animation-name",
|
||||||
|
"animation-name",
|
||||||
|
"-webkit-animation-duration",
|
||||||
|
"-moz-animation-duration",
|
||||||
|
"-ms-animation-duration",
|
||||||
|
"-o-animation-duration",
|
||||||
|
"animation-duration",
|
||||||
|
"-webkit-animation-play-state",
|
||||||
|
"-moz-animation-play-state",
|
||||||
|
"-ms-animation-play-state",
|
||||||
|
"-o-animation-play-state",
|
||||||
|
"animation-play-state",
|
||||||
|
"-webkit-animation-timing-function",
|
||||||
|
"-moz-animation-timing-function",
|
||||||
|
"-ms-animation-timing-function",
|
||||||
|
"-o-animation-timing-function",
|
||||||
|
"animation-timing-function",
|
||||||
|
"-webkit-animation-delay",
|
||||||
|
"-moz-animation-delay",
|
||||||
|
"-ms-animation-delay",
|
||||||
|
"-o-animation-delay",
|
||||||
|
"animation-delay",
|
||||||
|
"-webkit-animation-iteration-count",
|
||||||
|
"-moz-animation-iteration-count",
|
||||||
|
"-ms-animation-iteration-count",
|
||||||
|
"-o-animation-iteration-count",
|
||||||
|
"animation-iteration-count",
|
||||||
|
"-webkit-animation-direction",
|
||||||
|
"-moz-animation-direction",
|
||||||
|
"-ms-animation-direction",
|
||||||
|
"-o-animation-direction",
|
||||||
|
"animation-direction"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
# editorconfig.org
|
||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
end_of_line = lf
|
||||||
|
charset = utf-8
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
insert_final_newline = true
|
||||||
|
|
||||||
|
[*.md]
|
||||||
|
trim_trailing_whitespace = false
|
|
@ -55,7 +55,7 @@
|
||||||
"max-statements": [0, 10],
|
"max-statements": [0, 10],
|
||||||
"new-parens": [2],
|
"new-parens": [2],
|
||||||
"new-cap": [2, {
|
"new-cap": [2, {
|
||||||
"capIsNewExceptions": ["ToInteger", "ToObject", "ToPrimitive", "ToUint32"]
|
"capIsNewExceptions": ["CSSModules", "ToInteger", "ToObject", "ToPrimitive", "ToUint32"]
|
||||||
}],
|
}],
|
||||||
"newline-after-var": [0],
|
"newline-after-var": [0],
|
||||||
"no-alert": [2],
|
"no-alert": [2],
|
||||||
|
|
|
@ -0,0 +1,458 @@
|
||||||
|
scss_files: "./components/**/*.scss"
|
||||||
|
|
||||||
|
linters:
|
||||||
|
BangFormat:
|
||||||
|
enabled: true
|
||||||
|
space_before_bang: true
|
||||||
|
space_after_bang: false
|
||||||
|
|
||||||
|
BorderZero:
|
||||||
|
enabled: true
|
||||||
|
|
||||||
|
ColorKeyword:
|
||||||
|
enabled: true
|
||||||
|
|
||||||
|
ColorVariable:
|
||||||
|
enabled: false
|
||||||
|
|
||||||
|
Comment:
|
||||||
|
enabled: true
|
||||||
|
exclude: []
|
||||||
|
|
||||||
|
DebugStatement:
|
||||||
|
enabled: true
|
||||||
|
|
||||||
|
DeclarationOrder:
|
||||||
|
enabled: false
|
||||||
|
|
||||||
|
DuplicateProperty:
|
||||||
|
enabled: true
|
||||||
|
exclude: []
|
||||||
|
|
||||||
|
ElsePlacement:
|
||||||
|
enabled: true
|
||||||
|
style: same_line # or 'new_line'
|
||||||
|
|
||||||
|
EmptyLineBetweenBlocks:
|
||||||
|
enabled: false
|
||||||
|
ignore_single_line_blocks: true
|
||||||
|
|
||||||
|
EmptyRule:
|
||||||
|
enabled: true
|
||||||
|
|
||||||
|
FinalNewline:
|
||||||
|
enabled: true
|
||||||
|
present: true
|
||||||
|
|
||||||
|
HexLength:
|
||||||
|
enabled: true
|
||||||
|
style: short # or 'long'
|
||||||
|
|
||||||
|
HexNotation:
|
||||||
|
enabled: true
|
||||||
|
style: lowercase # or 'uppercase'
|
||||||
|
|
||||||
|
HexValidation:
|
||||||
|
enabled: true
|
||||||
|
|
||||||
|
IdSelector:
|
||||||
|
enabled: true
|
||||||
|
|
||||||
|
ImportantRule:
|
||||||
|
enabled: false
|
||||||
|
|
||||||
|
ImportPath:
|
||||||
|
enabled: true
|
||||||
|
leading_underscore: false
|
||||||
|
filename_extension: false
|
||||||
|
|
||||||
|
Indentation:
|
||||||
|
enabled: true
|
||||||
|
character: space # or 'tab'
|
||||||
|
width: 2
|
||||||
|
|
||||||
|
LeadingZero:
|
||||||
|
enabled: false
|
||||||
|
style: exclude_zero # or 'include_zero'
|
||||||
|
|
||||||
|
MergeableSelector:
|
||||||
|
enabled: false
|
||||||
|
force_nesting: true
|
||||||
|
|
||||||
|
NameFormat:
|
||||||
|
enabled: true
|
||||||
|
allow_leading_underscore: true
|
||||||
|
convention: hyphenated_lowercase # or 'BEM', or a regex pattern
|
||||||
|
|
||||||
|
NestingDepth:
|
||||||
|
enabled: false
|
||||||
|
|
||||||
|
PlaceholderInExtend:
|
||||||
|
enabled: false
|
||||||
|
|
||||||
|
PropertySortOrder:
|
||||||
|
enabled: true
|
||||||
|
ignore_unspecified: false
|
||||||
|
severity: warning
|
||||||
|
exclude: []
|
||||||
|
order: [
|
||||||
|
"position",
|
||||||
|
"top",
|
||||||
|
"right",
|
||||||
|
"bottom",
|
||||||
|
"left",
|
||||||
|
"z-index",
|
||||||
|
"-webkit-box-sizing",
|
||||||
|
"-moz-box-sizing",
|
||||||
|
"box-sizing",
|
||||||
|
"display",
|
||||||
|
"float",
|
||||||
|
"width",
|
||||||
|
"min-width",
|
||||||
|
"max-width",
|
||||||
|
"height",
|
||||||
|
"min-height",
|
||||||
|
"max-height",
|
||||||
|
"flex",
|
||||||
|
"flex-direction",
|
||||||
|
"flex-flow",
|
||||||
|
"flex-order",
|
||||||
|
"flex-pack",
|
||||||
|
"flex-align",
|
||||||
|
"padding",
|
||||||
|
"padding-top",
|
||||||
|
"padding-right",
|
||||||
|
"padding-bottom",
|
||||||
|
"padding-left",
|
||||||
|
"margin",
|
||||||
|
"margin-top",
|
||||||
|
"margin-right",
|
||||||
|
"margin-bottom",
|
||||||
|
"margin-left",
|
||||||
|
"overflow",
|
||||||
|
"overflow-x",
|
||||||
|
"overflow-y",
|
||||||
|
"-webkit-overflow-scrolling",
|
||||||
|
"-ms-overflow-x",
|
||||||
|
"-ms-overflow-y",
|
||||||
|
"-ms-overflow-style",
|
||||||
|
"clip",
|
||||||
|
"clear",
|
||||||
|
"font",
|
||||||
|
"font-family",
|
||||||
|
"font-size",
|
||||||
|
"font-style",
|
||||||
|
"font-weight",
|
||||||
|
"font-variant",
|
||||||
|
"font-size-adjust",
|
||||||
|
"font-stretch",
|
||||||
|
"font-effect",
|
||||||
|
"font-emphasize",
|
||||||
|
"font-emphasize-position",
|
||||||
|
"font-emphasize-style",
|
||||||
|
"font-smooth",
|
||||||
|
"-webkit-hyphens",
|
||||||
|
"-moz-hyphens",
|
||||||
|
"hyphens",
|
||||||
|
"line-height",
|
||||||
|
"color",
|
||||||
|
"text-align",
|
||||||
|
"-webkit-text-align-last",
|
||||||
|
"-moz-text-align-last",
|
||||||
|
"-ms-text-align-last",
|
||||||
|
"text-align-last",
|
||||||
|
"text-emphasis",
|
||||||
|
"text-emphasis-color",
|
||||||
|
"text-emphasis-style",
|
||||||
|
"text-emphasis-position",
|
||||||
|
"text-decoration",
|
||||||
|
"text-indent",
|
||||||
|
"text-justify",
|
||||||
|
"text-outline",
|
||||||
|
"-ms-text-overflow",
|
||||||
|
"text-overflow",
|
||||||
|
"text-overflow-ellipsis",
|
||||||
|
"text-overflow-mode",
|
||||||
|
"text-shadow",
|
||||||
|
"text-transform",
|
||||||
|
"text-wrap",
|
||||||
|
"-webkit-text-size-adjust",
|
||||||
|
"-ms-text-size-adjust",
|
||||||
|
"letter-spacing",
|
||||||
|
"-ms-word-break",
|
||||||
|
"word-break",
|
||||||
|
"word-spacing",
|
||||||
|
"-ms-word-wrap",
|
||||||
|
"word-wrap",
|
||||||
|
"-moz-tab-size",
|
||||||
|
"-o-tab-size",
|
||||||
|
"tab-size",
|
||||||
|
"white-space",
|
||||||
|
"vertical-align",
|
||||||
|
"list-style",
|
||||||
|
"list-style-position",
|
||||||
|
"list-style-type",
|
||||||
|
"list-style-image",
|
||||||
|
"pointer-events",
|
||||||
|
"-ms-touch-action",
|
||||||
|
"touch-action",
|
||||||
|
"cursor",
|
||||||
|
"visibility",
|
||||||
|
"zoom",
|
||||||
|
"table-layout",
|
||||||
|
"empty-cells",
|
||||||
|
"caption-side",
|
||||||
|
"border-spacing",
|
||||||
|
"border-collapse",
|
||||||
|
"content",
|
||||||
|
"quotes",
|
||||||
|
"counter-reset",
|
||||||
|
"counter-increment",
|
||||||
|
"resize",
|
||||||
|
"-webkit-user-select",
|
||||||
|
"-moz-user-select",
|
||||||
|
"-ms-user-select",
|
||||||
|
"-o-user-select",
|
||||||
|
"user-select",
|
||||||
|
"nav-index",
|
||||||
|
"nav-up",
|
||||||
|
"nav-right",
|
||||||
|
"nav-down",
|
||||||
|
"nav-left",
|
||||||
|
"background",
|
||||||
|
"background-color",
|
||||||
|
"background-image",
|
||||||
|
"-ms-filter:\\'progid:DXImageTransform.Microsoft.gradient",
|
||||||
|
"filter:progid:DXImageTransform.Microsoft.gradient",
|
||||||
|
"filter:progid:DXImageTransform.Microsoft.AlphaImageLoader",
|
||||||
|
"filter",
|
||||||
|
"background-repeat",
|
||||||
|
"background-attachment",
|
||||||
|
"background-position",
|
||||||
|
"background-position-x",
|
||||||
|
"background-position-y",
|
||||||
|
"-webkit-background-clip",
|
||||||
|
"-moz-background-clip",
|
||||||
|
"background-clip",
|
||||||
|
"background-origin",
|
||||||
|
"-webkit-background-size",
|
||||||
|
"-moz-background-size",
|
||||||
|
"-o-background-size",
|
||||||
|
"background-size",
|
||||||
|
"border",
|
||||||
|
"border-color",
|
||||||
|
"border-style",
|
||||||
|
"border-width",
|
||||||
|
"border-top",
|
||||||
|
"border-top-color",
|
||||||
|
"border-top-style",
|
||||||
|
"border-top-width",
|
||||||
|
"border-right",
|
||||||
|
"border-right-color",
|
||||||
|
"border-right-style",
|
||||||
|
"border-right-width",
|
||||||
|
"border-bottom",
|
||||||
|
"border-bottom-color",
|
||||||
|
"border-bottom-style",
|
||||||
|
"border-bottom-width",
|
||||||
|
"border-left",
|
||||||
|
"border-left-color",
|
||||||
|
"border-left-style",
|
||||||
|
"border-left-width",
|
||||||
|
"border-radius",
|
||||||
|
"border-top-left-radius",
|
||||||
|
"border-top-right-radius",
|
||||||
|
"border-bottom-right-radius",
|
||||||
|
"border-bottom-left-radius",
|
||||||
|
"-webkit-border-image",
|
||||||
|
"-moz-border-image",
|
||||||
|
"-o-border-image",
|
||||||
|
"border-image",
|
||||||
|
"-webkit-border-image-source",
|
||||||
|
"-moz-border-image-source",
|
||||||
|
"-o-border-image-source",
|
||||||
|
"border-image-source",
|
||||||
|
"-webkit-border-image-slice",
|
||||||
|
"-moz-border-image-slice",
|
||||||
|
"-o-border-image-slice",
|
||||||
|
"border-image-slice",
|
||||||
|
"-webkit-border-image-width",
|
||||||
|
"-moz-border-image-width",
|
||||||
|
"-o-border-image-width",
|
||||||
|
"border-image-width",
|
||||||
|
"-webkit-border-image-outset",
|
||||||
|
"-moz-border-image-outset",
|
||||||
|
"-o-border-image-outset",
|
||||||
|
"border-image-outset",
|
||||||
|
"-webkit-border-image-repeat",
|
||||||
|
"-moz-border-image-repeat",
|
||||||
|
"-o-border-image-repeat",
|
||||||
|
"border-image-repeat",
|
||||||
|
"outline",
|
||||||
|
"outline-width",
|
||||||
|
"outline-style",
|
||||||
|
"outline-color",
|
||||||
|
"outline-offset",
|
||||||
|
"-webkit-box-shadow",
|
||||||
|
"-moz-box-shadow",
|
||||||
|
"box-shadow",
|
||||||
|
"filter:progid:DXImageTransform.Microsoft.Alpha(Opacity",
|
||||||
|
"-ms-filter:\\'progid:DXImageTransform.Microsoft.Alpha",
|
||||||
|
"opacity",
|
||||||
|
"-ms-interpolation-mode",
|
||||||
|
"-webkit-transition",
|
||||||
|
"-moz-transition",
|
||||||
|
"-ms-transition",
|
||||||
|
"-o-transition",
|
||||||
|
"transition",
|
||||||
|
"-webkit-transition-delay",
|
||||||
|
"-moz-transition-delay",
|
||||||
|
"-ms-transition-delay",
|
||||||
|
"-o-transition-delay",
|
||||||
|
"transition-delay",
|
||||||
|
"-webkit-transition-timing-function",
|
||||||
|
"-moz-transition-timing-function",
|
||||||
|
"-ms-transition-timing-function",
|
||||||
|
"-o-transition-timing-function",
|
||||||
|
"transition-timing-function",
|
||||||
|
"-webkit-transition-duration",
|
||||||
|
"-moz-transition-duration",
|
||||||
|
"-ms-transition-duration",
|
||||||
|
"-o-transition-duration",
|
||||||
|
"transition-duration",
|
||||||
|
"-webkit-transition-property",
|
||||||
|
"-moz-transition-property",
|
||||||
|
"-ms-transition-property",
|
||||||
|
"-o-transition-property",
|
||||||
|
"transition-property",
|
||||||
|
"-webkit-transform",
|
||||||
|
"-moz-transform",
|
||||||
|
"-ms-transform",
|
||||||
|
"-o-transform",
|
||||||
|
"transform",
|
||||||
|
"-webkit-transform-origin",
|
||||||
|
"-moz-transform-origin",
|
||||||
|
"-ms-transform-origin",
|
||||||
|
"-o-transform-origin",
|
||||||
|
"transform-origin",
|
||||||
|
"-webkit-animation",
|
||||||
|
"-moz-animation",
|
||||||
|
"-ms-animation",
|
||||||
|
"-o-animation",
|
||||||
|
"animation",
|
||||||
|
"-webkit-animation-name",
|
||||||
|
"-moz-animation-name",
|
||||||
|
"-ms-animation-name",
|
||||||
|
"-o-animation-name",
|
||||||
|
"animation-name",
|
||||||
|
"-webkit-animation-duration",
|
||||||
|
"-moz-animation-duration",
|
||||||
|
"-ms-animation-duration",
|
||||||
|
"-o-animation-duration",
|
||||||
|
"animation-duration",
|
||||||
|
"-webkit-animation-play-state",
|
||||||
|
"-moz-animation-play-state",
|
||||||
|
"-ms-animation-play-state",
|
||||||
|
"-o-animation-play-state",
|
||||||
|
"animation-play-state",
|
||||||
|
"-webkit-animation-timing-function",
|
||||||
|
"-moz-animation-timing-function",
|
||||||
|
"-ms-animation-timing-function",
|
||||||
|
"-o-animation-timing-function",
|
||||||
|
"animation-timing-function",
|
||||||
|
"-webkit-animation-delay",
|
||||||
|
"-moz-animation-delay",
|
||||||
|
"-ms-animation-delay",
|
||||||
|
"-o-animation-delay",
|
||||||
|
"animation-delay",
|
||||||
|
"-webkit-animation-iteration-count",
|
||||||
|
"-moz-animation-iteration-count",
|
||||||
|
"-ms-animation-iteration-count",
|
||||||
|
"-o-animation-iteration-count",
|
||||||
|
"animation-iteration-count",
|
||||||
|
"-webkit-animation-direction",
|
||||||
|
"-moz-animation-direction",
|
||||||
|
"-ms-animation-direction",
|
||||||
|
"-o-animation-direction",
|
||||||
|
"animation-direction"
|
||||||
|
]
|
||||||
|
|
||||||
|
PropertySpelling:
|
||||||
|
enabled: true
|
||||||
|
extra_properties: [composes]
|
||||||
|
|
||||||
|
QualifyingElement:
|
||||||
|
enabled: false
|
||||||
|
allow_element_with_attribute: false
|
||||||
|
allow_element_with_class: false
|
||||||
|
allow_element_with_id: false
|
||||||
|
|
||||||
|
SelectorDepth:
|
||||||
|
enabled: false
|
||||||
|
|
||||||
|
SelectorFormat:
|
||||||
|
enabled: true
|
||||||
|
convention: hyphenated_lowercase # or 'BEM', or 'snake_case', or 'camel_case', or a regex pattern
|
||||||
|
|
||||||
|
Shorthand:
|
||||||
|
enabled: true
|
||||||
|
|
||||||
|
SingleLinePerProperty:
|
||||||
|
enabled: true
|
||||||
|
allow_single_line_rule_sets: true
|
||||||
|
|
||||||
|
SingleLinePerSelector:
|
||||||
|
enabled: false
|
||||||
|
|
||||||
|
SpaceAfterComma:
|
||||||
|
enabled: false
|
||||||
|
|
||||||
|
SpaceAfterPropertyColon:
|
||||||
|
enabled: true
|
||||||
|
style: at_least_one_space # or 'no_space', or 'at_least_one_space', or 'aligned'
|
||||||
|
|
||||||
|
SpaceAfterPropertyName:
|
||||||
|
enabled: true
|
||||||
|
|
||||||
|
SpaceBeforeBrace:
|
||||||
|
enabled: true
|
||||||
|
style: space
|
||||||
|
allow_single_line_padding: true
|
||||||
|
|
||||||
|
SpaceBetweenParens:
|
||||||
|
enabled: true
|
||||||
|
spaces: 0
|
||||||
|
|
||||||
|
StringQuotes:
|
||||||
|
enabled: true
|
||||||
|
style: double_quotes
|
||||||
|
|
||||||
|
TrailingSemicolon:
|
||||||
|
enabled: true
|
||||||
|
|
||||||
|
TrailingZero:
|
||||||
|
enabled: false
|
||||||
|
|
||||||
|
UnnecessaryMantissa:
|
||||||
|
enabled: true
|
||||||
|
|
||||||
|
UnnecessaryParentReference:
|
||||||
|
enabled: true
|
||||||
|
|
||||||
|
UrlFormat:
|
||||||
|
enabled: true
|
||||||
|
|
||||||
|
UrlQuotes:
|
||||||
|
enabled: true
|
||||||
|
|
||||||
|
VendorPrefixes:
|
||||||
|
enabled: true
|
||||||
|
identifier_list: base
|
||||||
|
include: []
|
||||||
|
exclude: []
|
||||||
|
|
||||||
|
ZeroUnit:
|
||||||
|
enabled: true
|
||||||
|
|
||||||
|
Compass::*:
|
||||||
|
enabled: false
|
|
@ -0,0 +1,4 @@
|
||||||
|
module.exports = {
|
||||||
|
SlideLeft: require('./slide-left'),
|
||||||
|
SlideRight: require('./slide-right')
|
||||||
|
};
|
|
@ -0,0 +1,28 @@
|
||||||
|
@import "../variables";
|
||||||
|
|
||||||
|
.enter, .leave {
|
||||||
|
position: absolute;
|
||||||
|
transition-timing-function: ease-in-out;
|
||||||
|
transition-duration: .35s;
|
||||||
|
transition-property: transform, opacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
.enter {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translate3d(-100%, 0, 0);
|
||||||
|
|
||||||
|
&.enterActive {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translate3d(0, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.leave {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translate3d(0, 0, 0);
|
||||||
|
|
||||||
|
&.leaveActive {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translate3d(100%, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
@import "../variables";
|
||||||
|
|
||||||
|
.enter, .leave {
|
||||||
|
position: absolute;
|
||||||
|
transition-timing-function: ease-in-out;
|
||||||
|
transition-duration: .35s;
|
||||||
|
transition-property: transform, opacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
.enter {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translate3d(100%, 0, 0);
|
||||||
|
|
||||||
|
&.enterActive {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translate3d(0, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.leave {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translate3d(0, 0, 0);
|
||||||
|
|
||||||
|
&.leaveActive {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translate3d(-100%, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
|
@ -26,7 +26,6 @@ var data = [
|
||||||
| **multiple** | Bool | true | If true, component can hold multiple values.|
|
| **multiple** | Bool | true | If true, component can hold multiple values.|
|
||||||
| **onChange** | Function | | Callback function that is fired when the components's value changes.|
|
| **onChange** | Function | | Callback function that is fired when the components's value changes.|
|
||||||
| **required** | Boolean | | If true, component needs has a value.|
|
| **required** | Boolean | | If true, component needs has a value.|
|
||||||
| **type** | String | "text" | Type of the component, overwrite this property if you need set a different stylesheet.|
|
|
||||||
| **value** | String | | Default value using JSON data.|
|
| **value** | String | | Default value using JSON data.|
|
||||||
|
|
||||||
## Methods
|
## Methods
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
/* global React */
|
import React from 'react';
|
||||||
|
import ReactDOM from 'react-dom';
|
||||||
import { addons } from 'react/addons';
|
import PureRenderMixin from 'react-addons-pure-render-mixin';
|
||||||
import css from './style';
|
|
||||||
import utils from '../utils';
|
import utils from '../utils';
|
||||||
import Input from '../input';
|
import Input from '../input';
|
||||||
|
import style from './style';
|
||||||
|
|
||||||
export default React.createClass({
|
export default React.createClass({
|
||||||
mixins: [addons.PureRenderMixin],
|
mixins: [PureRenderMixin],
|
||||||
|
|
||||||
displayName: 'Autocomplete',
|
displayName: 'Autocomplete',
|
||||||
|
|
||||||
|
@ -19,7 +19,6 @@ export default React.createClass({
|
||||||
multiple: React.PropTypes.bool,
|
multiple: React.PropTypes.bool,
|
||||||
onChange: React.PropTypes.func,
|
onChange: React.PropTypes.func,
|
||||||
required: React.PropTypes.bool,
|
required: React.PropTypes.bool,
|
||||||
type: React.PropTypes.string,
|
|
||||||
value: React.PropTypes.any
|
value: React.PropTypes.any
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -27,8 +26,7 @@ export default React.createClass({
|
||||||
return {
|
return {
|
||||||
className: '',
|
className: '',
|
||||||
dataSource: {},
|
dataSource: {},
|
||||||
multiple: true,
|
multiple: true
|
||||||
type: 'text'
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -37,12 +35,17 @@ export default React.createClass({
|
||||||
dataSource: this._indexDataSource(this.props.dataSource),
|
dataSource: this._indexDataSource(this.props.dataSource),
|
||||||
focus: false,
|
focus: false,
|
||||||
query: '',
|
query: '',
|
||||||
values: new Map()
|
up: false,
|
||||||
|
values: new Map(),
|
||||||
|
width: undefined
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
componentDidMount () {
|
componentDidMount () {
|
||||||
if (this.props.value) this.setValue(this.props.value);
|
if (this.props.value) this.setValue(this.props.value);
|
||||||
|
this.setState({
|
||||||
|
width: ReactDOM.findDOMNode(this).getBoundingClientRect().width
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
componentWillReceiveProps (props) {
|
componentWillReceiveProps (props) {
|
||||||
|
@ -77,8 +80,15 @@ export default React.createClass({
|
||||||
},
|
},
|
||||||
|
|
||||||
handleFocus () {
|
handleFocus () {
|
||||||
this.refs.suggestions.getDOMNode().scrollTop = 0;
|
let client = event.target.getBoundingClientRect();
|
||||||
this.setState({active: '', focus: true});
|
let screen_height = window.innerHeight || document.documentElement.offsetHeight;
|
||||||
|
|
||||||
|
this.refs.suggestions.scrollTop = 0;
|
||||||
|
this.setState({
|
||||||
|
active: '',
|
||||||
|
up: client.top > ((screen_height / 2) + client.height),
|
||||||
|
focus: true
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
handleBlur () {
|
handleBlur () {
|
||||||
|
@ -162,40 +172,54 @@ export default React.createClass({
|
||||||
renderSelected () {
|
renderSelected () {
|
||||||
if (this.props.multiple) {
|
if (this.props.multiple) {
|
||||||
return (
|
return (
|
||||||
<ul className={css.values} data-flex='horizontal wrap' onClick={this.handleUnselect}>
|
<ul data-flex='horizontal wrap' onClick={this.handleUnselect}>
|
||||||
{[...this.state.values].map(([key, value]) => {
|
{[...this.state.values].map(([key, value]) => {
|
||||||
return (<li key={key} id={key}>{value}</li>);
|
return (<li className={style.value} key={key} id={key}>{value}</li>);
|
||||||
})}
|
})}
|
||||||
</ul>
|
</ul>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
renderSuggestions () {
|
||||||
|
return [...this._getSuggestions()].map(([key, value]) => {
|
||||||
|
let className = style.suggestion;
|
||||||
|
if (this.state.active === key) className += ` ${style.active}`;
|
||||||
|
return <li id={key} key={key} className={className}>{value}</li>;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
let className = `${css.root} ${this.props.className}`;
|
let className = style.root;
|
||||||
if (this.props.type) className += ` ${this.props.type}`;
|
if (this.props.className) className += ` ${this.props.className}`;
|
||||||
if (this.state.focus) className += ' focus';
|
if (this.state.focus) className += ` ${style.focus}`;
|
||||||
|
|
||||||
|
let suggestionsClassName = style.suggestions;
|
||||||
|
if (this.state.up) suggestionsClassName += ` ${style.up}`;
|
||||||
|
let suggestionsStyle = {width: this.state.width};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div data-react-toolbox='autocomplete' className={className}>
|
<div data-react-toolbox='autocomplete' className={className}>
|
||||||
{this.props.label ? (<label>{this.props.label}</label>) : ''}
|
{this.props.label ? <label className={style.label}>{this.props.label}</label> : ''}
|
||||||
{this.renderSelected()}
|
{this.renderSelected()}
|
||||||
<Input {...this.props} ref='input' label='' value=''
|
<Input
|
||||||
onBlur={this.handleBlur}
|
ref='input'
|
||||||
onChange={this.handleQueryChange}
|
{...this.props}
|
||||||
onFocus={this.handleFocus}
|
label=''
|
||||||
onKeyUp={this.handleKeyPress} />
|
value=''
|
||||||
<ul ref='suggestions'
|
className={style.input}
|
||||||
className={css.suggestions}
|
onBlur={this.handleBlur}
|
||||||
onMouseDown={this.handleSelect}
|
onChange={this.handleQueryChange}
|
||||||
onMouseOver={this.handleHover}>
|
onFocus={this.handleFocus}
|
||||||
{[...this._getSuggestions()].map(([key, value]) => {
|
onKeyUp={this.handleKeyPress} />
|
||||||
return (
|
<ul
|
||||||
<li id={key} key={key} className={this.state.active === key ? 'active' : ''}>
|
ref='suggestions'
|
||||||
{value}
|
className={suggestionsClassName}
|
||||||
</li>
|
onMouseDown={this.handleSelect}
|
||||||
);
|
onMouseOver={this.handleHover}
|
||||||
})}
|
style={suggestionsStyle}
|
||||||
|
>
|
||||||
|
{this.renderSuggestions()}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -0,0 +1,75 @@
|
||||||
|
@import "../variables";
|
||||||
|
@import "../mixins";
|
||||||
|
|
||||||
|
$autocomplete-color-primary: unquote("rgb(#{$color-primary})");
|
||||||
|
$autocomplete-color-primary-contrast: unquote("rgb(#{$color-primary-contrast})");
|
||||||
|
$autocomplete-color-white: unquote("rgb(#{$color-white})");
|
||||||
|
$autocomplete-suggestion-color-active: unquote("rgb(#{$palette-grey-200})");
|
||||||
|
|
||||||
|
.root {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&.focus {
|
||||||
|
.label {
|
||||||
|
color: $autocomplete-color-primary;
|
||||||
|
}
|
||||||
|
|
||||||
|
.suggestions {
|
||||||
|
max-height: $items-overflow-max-height;
|
||||||
|
visibility: visible;
|
||||||
|
box-shadow: $zdepth-shadow-1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.label {
|
||||||
|
font-size: $font-size-tiny;
|
||||||
|
color: $color-text-secondary;
|
||||||
|
transition: color $animation-duration $animation-curve-default;
|
||||||
|
}
|
||||||
|
|
||||||
|
.value {
|
||||||
|
display: inline-block;
|
||||||
|
padding: $unit * .5 $unit * .75;
|
||||||
|
margin: $unit * .25 $unit * .5 $unit * .25 0;
|
||||||
|
font-size: $font-size-tiny;
|
||||||
|
color: $autocomplete-color-primary-contrast;
|
||||||
|
cursor: pointer;
|
||||||
|
background-color: $autocomplete-color-primary;
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.suggestions {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 2;
|
||||||
|
max-height: 0;
|
||||||
|
overflow-x: hidden;
|
||||||
|
overflow-y: scroll;
|
||||||
|
visibility: hidden;
|
||||||
|
background-color: $autocomplete-color-white;
|
||||||
|
transition-timing-function: $animation-curve-default;
|
||||||
|
transition-duration: $animation-duration;
|
||||||
|
transition-property: max-height, box-shadow;
|
||||||
|
|
||||||
|
&:not(.up) {
|
||||||
|
bottom: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.up {
|
||||||
|
top: auto;
|
||||||
|
bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.suggestion {
|
||||||
|
padding: $unit;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
background-color: $autocomplete-suggestion-color-active;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.input {
|
||||||
|
padding-bottom: 0;
|
||||||
|
}
|
|
@ -1,47 +0,0 @@
|
||||||
@import '../constants'
|
|
||||||
|
|
||||||
:local(.values)
|
|
||||||
> *
|
|
||||||
display : inline-block
|
|
||||||
margin : 0 (SPACE / 2) (SPACE / 2) 0
|
|
||||||
padding : (SPACE / 4) (SPACE / 2)
|
|
||||||
font-size : FONT_SIZE_SMALL
|
|
||||||
color : WHITE
|
|
||||||
background-color : PRIMARY
|
|
||||||
border-radius : (SPACE / 8)
|
|
||||||
cursor : pointer
|
|
||||||
|
|
||||||
:local(.suggestions)
|
|
||||||
z-index : 2
|
|
||||||
position : absolute
|
|
||||||
width : 100%
|
|
||||||
height : 0
|
|
||||||
max-height : 50vh
|
|
||||||
overflow-x : hidden
|
|
||||||
overflow-y : scroll
|
|
||||||
margin-top : -(SPACE)
|
|
||||||
background-color : WHITE
|
|
||||||
opacity : 0
|
|
||||||
transform : translateY(-(INPUT_HEIGHT / 2))
|
|
||||||
transition-property : height, box-shadow, opacity, transform
|
|
||||||
transition-duration : ANIMATION_DURATION
|
|
||||||
transition-timing-function : ANIMATION_EASE
|
|
||||||
> *
|
|
||||||
cursor : pointer
|
|
||||||
padding : (SPACE / 2)
|
|
||||||
&.active
|
|
||||||
color : WHITE
|
|
||||||
background-color : PRIMARY_LIGHT
|
|
||||||
|
|
||||||
:local(.root)
|
|
||||||
position : relative
|
|
||||||
> label
|
|
||||||
font-size : FONT_SIZE_TINY
|
|
||||||
color : PRIMARY
|
|
||||||
// -- Overrides
|
|
||||||
&.focus
|
|
||||||
> :local(.suggestions)
|
|
||||||
height : auto
|
|
||||||
opacity : 1
|
|
||||||
transform : translateY(0%)
|
|
||||||
box-shadow : ZDEPTH_SHADOW_1
|
|
|
@ -1,12 +1,12 @@
|
||||||
/* global React */
|
import React from 'react';
|
||||||
|
import PureRenderMixin from 'react-addons-pure-render-mixin';
|
||||||
import { addons } from 'react/addons';
|
|
||||||
import css from './style';
|
|
||||||
import FontIcon from '../font_icon';
|
import FontIcon from '../font_icon';
|
||||||
import Ripple from '../ripple';
|
import Ripple from '../ripple';
|
||||||
|
import style from './style.scss';
|
||||||
|
import events from '../utils/events';
|
||||||
|
|
||||||
export default React.createClass({
|
export default React.createClass({
|
||||||
mixins: [addons.PureRenderMixin],
|
mixins: [PureRenderMixin],
|
||||||
|
|
||||||
displayName: 'Button',
|
displayName: 'Button',
|
||||||
|
|
||||||
|
@ -14,6 +14,8 @@ export default React.createClass({
|
||||||
className: React.PropTypes.string,
|
className: React.PropTypes.string,
|
||||||
disabled: React.PropTypes.bool,
|
disabled: React.PropTypes.bool,
|
||||||
icon: React.PropTypes.string,
|
icon: React.PropTypes.string,
|
||||||
|
primary: React.PropTypes.bool,
|
||||||
|
accent: React.PropTypes.bool,
|
||||||
label: React.PropTypes.string,
|
label: React.PropTypes.string,
|
||||||
loading: React.PropTypes.bool,
|
loading: React.PropTypes.bool,
|
||||||
ripple: React.PropTypes.bool,
|
ripple: React.PropTypes.bool,
|
||||||
|
@ -32,26 +34,29 @@ export default React.createClass({
|
||||||
return { loading: this.props.loading };
|
return { loading: this.props.loading };
|
||||||
},
|
},
|
||||||
|
|
||||||
handleClick (event) {
|
handleMouseDown (event) {
|
||||||
if (this.props.onClick) this.props.onClick(event, this);
|
events.pauseEvent(event);
|
||||||
|
this.refs.ripple.start(event);
|
||||||
},
|
},
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
let className = this.props.className;
|
let className = style[this.props.type];
|
||||||
if (this.props.type) className += ` ${this.props.type}`;
|
if (this.props.className) className += ` ${this.props.className}`;
|
||||||
if (this.state.focused) className += ' focused';
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
className={css.root + ' ' + className}
|
|
||||||
data-flex='horizontal center'
|
|
||||||
data-react-toolbox='button'
|
data-react-toolbox='button'
|
||||||
|
{...this.props}
|
||||||
|
type=''
|
||||||
|
label=''
|
||||||
|
data-toolbox='button'
|
||||||
|
className={className}
|
||||||
disabled={this.props.disabled || this.state.loading}
|
disabled={this.props.disabled || this.state.loading}
|
||||||
onClick={this.handleClick}
|
onMouseDown={this.handleMouseDown}
|
||||||
>
|
>
|
||||||
{ this.props.icon ? <FontIcon value={this.props.icon}/> : null }
|
{ this.props.ripple ? <Ripple ref='ripple' loading={this.props.loading}/> : null }
|
||||||
{ this.props.label ? <abbr>{this.props.label}</abbr> : null }
|
{ this.props.icon ? <FontIcon className={style.icon} value={this.props.icon}/> : null }
|
||||||
{ this.props.ripple ? <Ripple loading={this.props.loading}/> : null }
|
{ this.props.label ? <abbr className={style.label}>{this.props.label}</abbr> : null }
|
||||||
</button>
|
</button>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
|
@ -0,0 +1,185 @@
|
||||||
|
@import "../variables";
|
||||||
|
@import "../mixins";
|
||||||
|
|
||||||
|
$button-default-text-color: unquote("rgb(#{$color-black})") !default;
|
||||||
|
$button-flat-color-hover: unquote("rgba(#{$color-black}, 0.26)") !default;
|
||||||
|
$button-disabled-text-color: unquote("rgba(#{$color-black}, 0.26)") !default;
|
||||||
|
$button-solid-background-color: unquote("rgba(#{$palette-grey-500}, 0.20)") !default;
|
||||||
|
$button-solid-disabled-background-color: unquote("rgba(#{$color-black}, 0.12)") !default;
|
||||||
|
$button-primary-color: unquote("rgb(#{$color-primary})") !default;
|
||||||
|
$button-primary-color-contrast: unquote("rgb(#{$color-primary-contrast})") !default;
|
||||||
|
$button-primary-color-hover: unquote("rgba(#{$color-primary}, 0.20)") !default;
|
||||||
|
$button-accent-color: unquote("rgb(#{$color-accent})") !default;
|
||||||
|
$button-accent-color-hover: unquote("rgba(#{$color-accent}, 0.20)") !default;
|
||||||
|
$button-accent-color-active: unquote("rgba(#{$color-accent}, 0.40)") !default;
|
||||||
|
$button-accent-color-contrast: unquote("rgb(#{$color-primary-contrast})") !default;
|
||||||
|
$button-height: $unit * 3.6;
|
||||||
|
$button-floating-height: $unit * 5.6;
|
||||||
|
$button-floating-height-mini: $unit * 4;
|
||||||
|
|
||||||
|
%button {
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
display: inline-block;
|
||||||
|
height: $button-height;
|
||||||
|
flex-direction: row;
|
||||||
|
overflow: hidden;
|
||||||
|
color: $button-default-text-color;
|
||||||
|
text-align: center;
|
||||||
|
text-decoration: none;
|
||||||
|
white-space: nowrap;
|
||||||
|
cursor: pointer;
|
||||||
|
border: 0;
|
||||||
|
outline: none;
|
||||||
|
transition: box-shadow .2s $animation-curve-fast-out-linear-in,
|
||||||
|
background-color .2s $animation-curve-default,
|
||||||
|
color .2s $animation-curve-default;
|
||||||
|
align-content: center;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
&::-moz-focus-inner {
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
%squared {
|
||||||
|
min-width: 9 * $unit;
|
||||||
|
padding: 0 $unit * 1.2;
|
||||||
|
border-radius: $border-radius;
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
margin-right: $unit * .6;
|
||||||
|
font-size: 120%;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
%disabled {
|
||||||
|
color: $button-disabled-text-color;
|
||||||
|
pointer-events: none;
|
||||||
|
cursor: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-- Local styles
|
||||||
|
.label {
|
||||||
|
@include typo-button();
|
||||||
|
line-height: $button-height;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flat {
|
||||||
|
@extend %button;
|
||||||
|
@extend %squared;
|
||||||
|
background: transparent;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: $button-flat-color-hover;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus:not(:active) {
|
||||||
|
background: $button-flat-color-hover;
|
||||||
|
}
|
||||||
|
|
||||||
|
&[disabled] {
|
||||||
|
@extend %disabled;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.raised {
|
||||||
|
@extend %button;
|
||||||
|
@extend %squared;
|
||||||
|
@include shadow-2dp();
|
||||||
|
background: $button-solid-background-color;
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
@include shadow-4dp();
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus:not(:active) {
|
||||||
|
@include focus-shadow();
|
||||||
|
}
|
||||||
|
|
||||||
|
&[disabled] {
|
||||||
|
@extend %disabled;
|
||||||
|
@include shadow-2dp();
|
||||||
|
background-color: $button-solid-disabled-background-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.floating {
|
||||||
|
@extend %button;
|
||||||
|
width: $button-floating-height;
|
||||||
|
height: $button-floating-height;
|
||||||
|
font-size: $unit * 2.4;
|
||||||
|
background: $button-solid-background-color;
|
||||||
|
border-radius: 50%;
|
||||||
|
box-shadow: 0 1px 1.5px 0 rgba(0, 0, 0, .12), 0 1px 1px 0 rgba(0, 0, 0, .24);
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
@include shadow-4dp();
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus:not(:active) {
|
||||||
|
@include focus-shadow();
|
||||||
|
}
|
||||||
|
|
||||||
|
&[disabled] {
|
||||||
|
@extend %disabled;
|
||||||
|
@include shadow-2dp();
|
||||||
|
background-color: $button-solid-disabled-background-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
line-height: $button-floating-height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(.primary):not([disabled]) {
|
||||||
|
&.raised, &.floating {
|
||||||
|
color: $button-primary-color-contrast;
|
||||||
|
background: $button-primary-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.flat {
|
||||||
|
color: $button-primary-color;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: $button-primary-color-hover;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus:not(:active) {
|
||||||
|
background: $button-primary-color-hover;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(.accent):not([disabled]) {
|
||||||
|
&.raised, &.floating {
|
||||||
|
color: $button-accent-color-contrast;
|
||||||
|
background-color: $button-accent-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.flat {
|
||||||
|
color: $button-accent-color;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: $button-accent-color-hover;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus:not(:active) {
|
||||||
|
background: $button-accent-color-hover;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(.mini) {
|
||||||
|
&.floating {
|
||||||
|
width: $button-floating-height-mini;
|
||||||
|
height: $button-floating-height-mini;
|
||||||
|
font-size: ($button-floating-height-mini / 2.25);
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
line-height: $button-floating-height-mini;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,85 +0,0 @@
|
||||||
@import '../constants'
|
|
||||||
|
|
||||||
:local(.root)
|
|
||||||
z-index : 1
|
|
||||||
display : inline-block
|
|
||||||
position : relative
|
|
||||||
overflow : hidden
|
|
||||||
font-weight : FONT_WEIGHT_NORMAL
|
|
||||||
text-align : center
|
|
||||||
text-decoration : none
|
|
||||||
white-space : nowrap
|
|
||||||
border : none
|
|
||||||
transition-property : background-color, box-shadow
|
|
||||||
transition-duration : ANIMATION_DURATION
|
|
||||||
transition-timing-function : ANIMATION_EASE
|
|
||||||
|
|
||||||
&.raised, &.flat
|
|
||||||
padding : (SPACE / 2) (SPACE / 1.25)
|
|
||||||
font-size : FONT_SIZE_SMALL
|
|
||||||
text-transform : uppercase
|
|
||||||
border-radius : (SPACE / 8)
|
|
||||||
> *
|
|
||||||
vertical-align : middle
|
|
||||||
> [data-react-toolbox='icon']
|
|
||||||
font-size : FONT_SIZE_BIG
|
|
||||||
margin-right : (SPACE / 2)
|
|
||||||
> abbr
|
|
||||||
font-weight : FONT_WEIGHT_BOLD
|
|
||||||
&.anchor
|
|
||||||
width : 100%
|
|
||||||
|
|
||||||
&.flat
|
|
||||||
background-color : transparent
|
|
||||||
&:not(.primary):not(.accent)
|
|
||||||
> [data-react-toolbox='ripple']
|
|
||||||
background-color : alpha(TEXT, 12.5%)
|
|
||||||
&.primary
|
|
||||||
color : PRIMARY
|
|
||||||
> [data-react-toolbox='ripple']
|
|
||||||
background-color : alpha(PRIMARY, 12.5%)
|
|
||||||
&.accent
|
|
||||||
color : ACCENT
|
|
||||||
> [data-react-toolbox='ripple']
|
|
||||||
background-color : alpha(ACCENT, 12.5%)
|
|
||||||
|
|
||||||
&.floating
|
|
||||||
width : BUTTON_CIRCLE_HEIGHT
|
|
||||||
height : BUTTON_CIRCLE_HEIGHT
|
|
||||||
font-size : (BUTTON_CIRCLE_HEIGHT / 2.25)
|
|
||||||
border-radius : 50%
|
|
||||||
> [data-react-toolbox='icon']
|
|
||||||
line-height : BUTTON_CIRCLE_HEIGHT
|
|
||||||
|
|
||||||
&.mini
|
|
||||||
width : BUTTON_CIRCLE_MINI_HEIGHT
|
|
||||||
height : BUTTON_CIRCLE_MINI_HEIGHT
|
|
||||||
> [data-react-toolbox='icon']
|
|
||||||
line-height : BUTTON_CIRCLE_MINI_HEIGHT
|
|
||||||
|
|
||||||
// Overrides
|
|
||||||
&[disabled]
|
|
||||||
color : darken(DIVIDER, 25%)
|
|
||||||
background-color : DIVIDER
|
|
||||||
pointer-events : none
|
|
||||||
|
|
||||||
&:not([disabled])
|
|
||||||
cursor : pointer
|
|
||||||
&:hover, &:active, &:focus
|
|
||||||
outline : 0
|
|
||||||
&:not(.flat)
|
|
||||||
box-shadow ZDEPTH_SHADOW_1
|
|
||||||
&:not(.primary):not(.accent)
|
|
||||||
color : TEXT
|
|
||||||
background-color : WHITE
|
|
||||||
&:active
|
|
||||||
box-shadow : ZDEPTH_SHADOW_2, inset 0 0 0 UNIT alpha(WHITE, 10%)
|
|
||||||
&.primary, &.accent
|
|
||||||
color : WHITE
|
|
||||||
&.primary
|
|
||||||
background-color : PRIMARY
|
|
||||||
&.accent
|
|
||||||
background-color : ACCENT
|
|
||||||
|
|
||||||
&:not(.primary):not(.accent) > [data-react-toolbox='ripple']
|
|
||||||
background-color : DIVIDER
|
|
|
@ -1,11 +1,10 @@
|
||||||
/* global React */
|
import React from 'react';
|
||||||
|
import PureRenderMixin from 'react-addons-pure-render-mixin';
|
||||||
import { addons } from 'react/addons';
|
import style from './style';
|
||||||
import css from './style';
|
|
||||||
import time from '../utils/time';
|
import time from '../utils/time';
|
||||||
|
|
||||||
export default React.createClass({
|
export default React.createClass({
|
||||||
mixins: [addons.PureRenderMixin],
|
mixins: [PureRenderMixin],
|
||||||
|
|
||||||
displayName: 'Day',
|
displayName: 'Day',
|
||||||
|
|
||||||
|
@ -33,7 +32,7 @@ export default React.createClass({
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
return (
|
return (
|
||||||
<div className={this.isSelected() ? `${css.day} active` : css.day} style={this.dayStyle()}>
|
<div className={this.isSelected() ? `${style.day} ${style.active}` : style.day} style={this.dayStyle()}>
|
||||||
<span onClick={this.props.onClick}>{this.props.day}</span>
|
<span onClick={this.props.onClick}>{this.props.day}</span>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
/* global React */
|
import React from 'react';
|
||||||
|
import PureRenderMixin from 'react-addons-pure-render-mixin';
|
||||||
import { addons } from 'react/addons';
|
import CSSTransitionGroup from 'react-addons-css-transition-group';
|
||||||
import css from './style';
|
import { SlideLeft, SlideRight } from '../animations';
|
||||||
import utils from '../utils';
|
|
||||||
import FontIcon from '../font_icon';
|
import FontIcon from '../font_icon';
|
||||||
|
import Ripple from '../ripple';
|
||||||
import Month from './month';
|
import Month from './month';
|
||||||
|
import style from './style';
|
||||||
const { CSSTransitionGroup: CTG } = React.addons;
|
import utils from '../utils';
|
||||||
|
|
||||||
export default React.createClass({
|
export default React.createClass({
|
||||||
mixins: [addons.PureRenderMixin],
|
mixins: [PureRenderMixin],
|
||||||
|
|
||||||
displayName: 'Calendar',
|
displayName: 'Calendar',
|
||||||
|
|
||||||
|
@ -40,26 +40,27 @@ export default React.createClass({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
onDayClick (event) {
|
onDayClick (day) {
|
||||||
let newDate = utils.time.setDay(this.state.viewDate, parseInt(event.target.textContent));
|
let newDate = utils.time.setDay(this.state.viewDate, day);
|
||||||
this.setState({selectedDate: newDate});
|
this.setState({selectedDate: newDate});
|
||||||
if (this.props.onChange) this.props.onChange(newDate);
|
if (this.props.onChange) this.props.onChange(newDate);
|
||||||
},
|
},
|
||||||
|
|
||||||
onYearClick (event) {
|
onYearClick (year) {
|
||||||
let newDate = utils.time.setYear(this.state.selectedDate, parseInt(event.target.textContent));
|
let newDate = utils.time.setYear(this.state.selectedDate, year);
|
||||||
this.setState({selectedDate: newDate, viewDate: newDate});
|
this.setState({selectedDate: newDate, viewDate: newDate});
|
||||||
if (this.props.onChange) this.props.onChange(newDate);
|
if (this.props.onChange) this.props.onChange(newDate);
|
||||||
},
|
},
|
||||||
|
|
||||||
scrollToActive () {
|
scrollToActive () {
|
||||||
this.refs.years.getDOMNode().scrollTop =
|
this.refs.years.scrollTop =
|
||||||
this.refs.activeYear.getDOMNode().offsetTop -
|
this.refs.activeYear.offsetTop -
|
||||||
this.refs.years.getDOMNode().offsetHeight / 2 +
|
this.refs.years.offsetHeight / 2 +
|
||||||
this.refs.activeYear.getDOMNode().offsetHeight / 2;
|
this.refs.activeYear.offsetHeight / 2;
|
||||||
},
|
},
|
||||||
|
|
||||||
incrementViewMonth () {
|
incrementViewMonth () {
|
||||||
|
this.refs.rippleRight.start(event);
|
||||||
this.setState({
|
this.setState({
|
||||||
direction: 'right',
|
direction: 'right',
|
||||||
viewDate: utils.time.addMonths(this.state.viewDate, 1)
|
viewDate: utils.time.addMonths(this.state.viewDate, 1)
|
||||||
|
@ -67,6 +68,7 @@ export default React.createClass({
|
||||||
},
|
},
|
||||||
|
|
||||||
decrementViewMonth () {
|
decrementViewMonth () {
|
||||||
|
this.refs.rippleLeft.start(event);
|
||||||
this.setState({
|
this.setState({
|
||||||
direction: 'left',
|
direction: 'left',
|
||||||
viewDate: utils.time.addMonths(this.state.viewDate, -1)
|
viewDate: utils.time.addMonths(this.state.viewDate, -1)
|
||||||
|
@ -75,9 +77,9 @@ export default React.createClass({
|
||||||
|
|
||||||
renderYear (year) {
|
renderYear (year) {
|
||||||
let props = {
|
let props = {
|
||||||
className: year === this.state.viewDate.getFullYear() ? 'active' : '',
|
className: year === this.state.viewDate.getFullYear() ? style.active : '',
|
||||||
key: `year-${year}`,
|
key: year,
|
||||||
onClick: this.onYearClick
|
onClick: this.onYearClick.bind(this, year)
|
||||||
};
|
};
|
||||||
|
|
||||||
if (year === this.state.viewDate.getFullYear()) {
|
if (year === this.state.viewDate.getFullYear()) {
|
||||||
|
@ -89,31 +91,36 @@ export default React.createClass({
|
||||||
|
|
||||||
renderYears () {
|
renderYears () {
|
||||||
return (
|
return (
|
||||||
<ul ref="years" className={css.years}>
|
<ul ref="years" className={style.years}>
|
||||||
{ utils.range(1900, 2100).map(i => { return this.renderYear(i); })}
|
{ utils.range(1900, 2100).map(i => { return this.renderYear(i); })}
|
||||||
</ul>
|
</ul>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
renderMonths () {
|
renderMonths () {
|
||||||
|
let animation = this.state.direction === 'left' ? SlideLeft : SlideRight;
|
||||||
return (
|
return (
|
||||||
<div className={this.state.direction}>
|
<div data-react-toolbox='calendar'>
|
||||||
<FontIcon className={css.prev} value='chevron_left' onClick={this.decrementViewMonth}/>
|
<FontIcon className={style.prev} value='chevron-left' onMouseDown={this.decrementViewMonth}>
|
||||||
<FontIcon className={css.next} value='chevron_right' onClick={this.incrementViewMonth}/>
|
<Ripple ref='rippleLeft' className={style.ripple} spread={1.2} centered />
|
||||||
<CTG transitionName='slide-horizontal'>
|
</FontIcon>
|
||||||
|
<FontIcon className={style.next} value='chevron-right' onMouseDown={this.incrementViewMonth}>
|
||||||
|
<Ripple ref='rippleRight' className={style.ripple} spread={1.2} centered />
|
||||||
|
</FontIcon>
|
||||||
|
<CSSTransitionGroup transitionName={animation} transitionEnterTimeout={350} transitionLeaveTimeout={350}>
|
||||||
<Month
|
<Month
|
||||||
key={this.state.viewDate.getMonth()}
|
key={this.state.viewDate.getMonth()}
|
||||||
viewDate={this.state.viewDate}
|
viewDate={this.state.viewDate}
|
||||||
selectedDate={this.state.selectedDate}
|
selectedDate={this.state.selectedDate}
|
||||||
onDayClick={this.onDayClick} />
|
onDayClick={this.onDayClick} />
|
||||||
</CTG>
|
</CSSTransitionGroup>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
return (
|
return (
|
||||||
<div className={css.root}>
|
<div className={style.root}>
|
||||||
{ this.props.display === 'months' ? this.renderMonths() : this.renderYears() }
|
{ this.props.display === 'months' ? this.renderMonths() : this.renderYears() }
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
/* global React */
|
import React from 'react';
|
||||||
|
import PureRenderMixin from 'react-addons-pure-render-mixin';
|
||||||
import { addons } from 'react/addons';
|
|
||||||
import css from './style';
|
|
||||||
import utils from '../utils';
|
|
||||||
import Day from './day';
|
import Day from './day';
|
||||||
|
import style from './style';
|
||||||
|
import utils from '../utils';
|
||||||
|
|
||||||
export default React.createClass({
|
export default React.createClass({
|
||||||
mixins: [addons.PureRenderMixin],
|
mixins: [PureRenderMixin],
|
||||||
|
|
||||||
displayName: 'Month',
|
displayName: 'Month',
|
||||||
|
|
||||||
|
@ -16,36 +15,38 @@ export default React.createClass({
|
||||||
viewDate: React.PropTypes.object
|
viewDate: React.PropTypes.object
|
||||||
},
|
},
|
||||||
|
|
||||||
|
handleDayClick (day) {
|
||||||
|
if (this.props.onDayClick) this.props.onDayClick(day);
|
||||||
|
},
|
||||||
|
|
||||||
renderWeeks () {
|
renderWeeks () {
|
||||||
return utils.range(0, 7).map(i => {
|
return utils.range(0, 7).map(i => {
|
||||||
return (
|
return <span key={i}>{ utils.time.getFullDayOfWeek(i).charAt(0) }</span>;
|
||||||
<span key={`dw${i}`}>
|
|
||||||
{ utils.time.getFullDayOfWeek(i).charAt(0) }
|
|
||||||
</span>
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
renderDays () {
|
renderDays () {
|
||||||
return utils.range(1, utils.time.getDaysInMonth(this.props.viewDate) + 1).map(i => {
|
return utils.range(1, utils.time.getDaysInMonth(this.props.viewDate) + 1).map(i => {
|
||||||
return (
|
return (
|
||||||
<Day key={`d${i}`}
|
<Day
|
||||||
|
key={i}
|
||||||
day={i}
|
day={i}
|
||||||
onClick={this.props.onDayClick}
|
onClick={this.handleDayClick.bind(this, i)}
|
||||||
selectedDate={this.props.selectedDate}
|
selectedDate={this.props.selectedDate}
|
||||||
viewDate={this.props.viewDate} />
|
viewDate={this.props.viewDate}
|
||||||
|
/>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div className={style.month}>
|
||||||
<span className={css.title}>
|
<span className={style.title}>
|
||||||
{ utils.time.getFullMonth(this.props.viewDate)} {this.props.viewDate.getFullYear() }
|
{ utils.time.getFullMonth(this.props.viewDate)} {this.props.viewDate.getFullYear() }
|
||||||
</span>
|
</span>
|
||||||
<div className={css.week}>{ this.renderWeeks() }</div>
|
<div className={style.week}>{ this.renderWeeks() }</div>
|
||||||
<div className={css.days}>{ this.renderDays() }</div>
|
<div className={style.days}>{ this.renderDays() }</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,114 @@
|
||||||
|
@import "../variables";
|
||||||
|
|
||||||
|
$calendar-primary: $color-primary;
|
||||||
|
$calendar-primary-contrast: $color-primary-contrast;
|
||||||
|
$calendar-primary-color: unquote("rgb(#{$calendar-primary})") !default;
|
||||||
|
$calendar-primary-contrast-color: unquote("rgb(#{$calendar-primary-contrast})") !default;
|
||||||
|
$calendar-primary-hover-color: unquote("rgba(#{$calendar-primary}, 0.21)") !default;
|
||||||
|
$calendar-arrows-color: unquote("rgb(#{$palette-grey-600})") !default;
|
||||||
|
$calendar-row-height: 3 * $unit;
|
||||||
|
$calendar-day-padding: .2 * $unit;
|
||||||
|
$calendar-total-height: $calendar-row-height * 8 + $calendar-day-padding * 12;
|
||||||
|
|
||||||
|
.root {
|
||||||
|
position: relative;
|
||||||
|
height: $calendar-total-height;
|
||||||
|
font-size: 1.4 * $unit;
|
||||||
|
line-height: $calendar-row-height;
|
||||||
|
text-align: center;
|
||||||
|
background: $calendar-primary-contrast-color;
|
||||||
|
|
||||||
|
.prev, .next {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
z-index: $z-index-high;
|
||||||
|
width: $calendar-row-height;
|
||||||
|
height: $calendar-row-height;
|
||||||
|
font-size: 2 * $unit;
|
||||||
|
line-height: $calendar-row-height;
|
||||||
|
color: $calendar-arrows-color;
|
||||||
|
text-align: center;
|
||||||
|
cursor: pointer;
|
||||||
|
opacity: .7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.prev {
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.next {
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.years {
|
||||||
|
height: 100%;
|
||||||
|
overflow: scroll;
|
||||||
|
font-size: 1.8 * $unit;
|
||||||
|
|
||||||
|
> li {
|
||||||
|
line-height: 2.4;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
font-size: 2.4 * $unit;
|
||||||
|
color: $calendar-primary-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.week {
|
||||||
|
display: flex;
|
||||||
|
height: $calendar-row-height;
|
||||||
|
font-size: 1.3 * $unit;
|
||||||
|
line-height: $calendar-row-height;
|
||||||
|
opacity: .5;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
|
||||||
|
> span {
|
||||||
|
flex: 0 0 (100% / 7);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.days {
|
||||||
|
display: flex;
|
||||||
|
font-size: 13px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
:local(.day) {
|
||||||
|
flex: 0 0 (100% / 7);
|
||||||
|
padding: $calendar-day-padding;
|
||||||
|
|
||||||
|
> span {
|
||||||
|
display: inline-block;
|
||||||
|
width: $calendar-row-height;
|
||||||
|
height: $calendar-row-height;
|
||||||
|
line-height: $calendar-row-height;
|
||||||
|
cursor: pointer;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover:not(.active) > span {
|
||||||
|
color: $calendar-primary-contrast-color;
|
||||||
|
background: $calendar-primary-hover-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active > span {
|
||||||
|
color: $calendar-primary-contrast-color;
|
||||||
|
background: $calendar-primary-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.month {
|
||||||
|
background-color: $calendar-primary-contrast-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ripple {
|
||||||
|
opacity: .5;
|
||||||
|
transition-duration: 450ms;
|
||||||
|
}
|
|
@ -1,118 +0,0 @@
|
||||||
@import '../constants'
|
|
||||||
|
|
||||||
// -- Calendar sizes
|
|
||||||
ROW_HEIGHT = 40px
|
|
||||||
DAY_PADDING = 2px
|
|
||||||
TOTAL_HEIGHT = ROW_HEIGHT * 8 + DAY_PADDING * 12
|
|
||||||
|
|
||||||
:local(.root)
|
|
||||||
background : WHITE
|
|
||||||
height : TOTAL_HEIGHT
|
|
||||||
font-size : 14px
|
|
||||||
overflow : hidden
|
|
||||||
position : relative
|
|
||||||
line-height : ROW_HEIGHT
|
|
||||||
text-align : center
|
|
||||||
|
|
||||||
:local(.prev), :local(.next)
|
|
||||||
color : lighten(TEXT, 15%)
|
|
||||||
cursor : pointer
|
|
||||||
font-size : 26px
|
|
||||||
height : ROW_HEIGHT
|
|
||||||
line-height : ROW_HEIGHT
|
|
||||||
opacity : .7
|
|
||||||
position : absolute
|
|
||||||
text-align : center
|
|
||||||
top : 0
|
|
||||||
width : ROW_HEIGHT
|
|
||||||
z-index : Z_INDEX_HIGH
|
|
||||||
|
|
||||||
:local(.title)
|
|
||||||
font-weight : 500
|
|
||||||
|
|
||||||
:local(.prev)
|
|
||||||
left : 0
|
|
||||||
|
|
||||||
:local(.next)
|
|
||||||
right : 0
|
|
||||||
|
|
||||||
:local(.week)
|
|
||||||
display : flex
|
|
||||||
flex-wrap : wrap
|
|
||||||
font-size : 13px
|
|
||||||
height : ROW_HEIGHT
|
|
||||||
line-height : ROW_HEIGHT
|
|
||||||
opacity : .5
|
|
||||||
|
|
||||||
> span
|
|
||||||
flex : 0 0 (100/7)%
|
|
||||||
|
|
||||||
:local(.days)
|
|
||||||
display : flex
|
|
||||||
flex-wrap : wrap
|
|
||||||
font-size : 13px
|
|
||||||
|
|
||||||
:local(.day)
|
|
||||||
flex : 0 0 (100/7)%
|
|
||||||
padding : DAY_PADDING
|
|
||||||
|
|
||||||
> span
|
|
||||||
border-radius : 50%
|
|
||||||
cursor : pointer
|
|
||||||
display : inline-block
|
|
||||||
height : ROW_HEIGHT
|
|
||||||
line-height : ROW_HEIGHT
|
|
||||||
width : ROW_HEIGHT
|
|
||||||
|
|
||||||
&:hover:not(.active) > span
|
|
||||||
background : lighten(ACCENT, 65%)
|
|
||||||
color : WHITE
|
|
||||||
|
|
||||||
&.active > span
|
|
||||||
background : ACCENT
|
|
||||||
color : WHITE
|
|
||||||
|
|
||||||
// -- Transitions
|
|
||||||
:local(.root) .slide-horizontal-enter, :local(.root) .slide-horizontal-leave
|
|
||||||
transition : all .5s
|
|
||||||
|
|
||||||
:local(.root) .right
|
|
||||||
.slide-horizontal-enter
|
|
||||||
position : absolute
|
|
||||||
transform : translateX(100%)
|
|
||||||
opacity : 0
|
|
||||||
|
|
||||||
.slide-horizontal-leave, .slide-horizontal-enter-active
|
|
||||||
transform : translateX(0)
|
|
||||||
opacity : 1
|
|
||||||
|
|
||||||
.slide-horizontal-leave-active
|
|
||||||
transform : translateX(-100%)
|
|
||||||
opacity : 0
|
|
||||||
|
|
||||||
:local(.root) .left
|
|
||||||
.slide-horizontal-enter
|
|
||||||
position : absolute
|
|
||||||
transform : translateX(-100%)
|
|
||||||
opacity : 0
|
|
||||||
|
|
||||||
.slide-horizontal-leave, .slide-horizontal-enter-active
|
|
||||||
transform : translateX(0)
|
|
||||||
opacity : 1
|
|
||||||
|
|
||||||
.slide-horizontal-leave-active
|
|
||||||
transform : translateX(100%)
|
|
||||||
opacity : 0
|
|
||||||
|
|
||||||
:local(.years)
|
|
||||||
font-size : 18px
|
|
||||||
height : 100%
|
|
||||||
overflow : scroll
|
|
||||||
|
|
||||||
> li
|
|
||||||
cursor : pointer
|
|
||||||
line-height : 2.4
|
|
||||||
|
|
||||||
&.active
|
|
||||||
color : ACCENT
|
|
||||||
font-size : 24px
|
|
|
@ -1,12 +1,11 @@
|
||||||
/* global React */
|
import React from 'react';
|
||||||
|
import PureRenderMixin from 'react-addons-pure-render-mixin';
|
||||||
import { addons } from 'react/addons';
|
|
||||||
import style from './style';
|
|
||||||
import Navigation from '../navigation';
|
import Navigation from '../navigation';
|
||||||
import Ripple from '../ripple';
|
import Ripple from '../ripple';
|
||||||
|
import style from './style.scss';
|
||||||
|
|
||||||
export default React.createClass({
|
export default React.createClass({
|
||||||
mixins: [addons.PureRenderMixin],
|
mixins: [PureRenderMixin],
|
||||||
|
|
||||||
displayName: 'Card',
|
displayName: 'Card',
|
||||||
|
|
||||||
|
@ -15,7 +14,6 @@ export default React.createClass({
|
||||||
color: React.PropTypes.string,
|
color: React.PropTypes.string,
|
||||||
image: React.PropTypes.string,
|
image: React.PropTypes.string,
|
||||||
text: React.PropTypes.string,
|
text: React.PropTypes.string,
|
||||||
legend: React.PropTypes.string,
|
|
||||||
loading: React.PropTypes.bool,
|
loading: React.PropTypes.bool,
|
||||||
onClick: React.PropTypes.func,
|
onClick: React.PropTypes.func,
|
||||||
title: React.PropTypes.string,
|
title: React.PropTypes.string,
|
||||||
|
@ -36,42 +34,66 @@ export default React.createClass({
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
onClick (event) {
|
handleMouseDown (event) {
|
||||||
if (this.props.onClick) {
|
if (this.props.onClick) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
this.refs.ripple.start(event);
|
||||||
this.props.onClick(event, this);
|
this.props.onClick(event, this);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
renderHeading () {
|
renderTitle () {
|
||||||
let headingStyle = {};
|
let styleFigure = {}, styleOverflow = {};
|
||||||
if (this.props.image) headingStyle.backgroundImage = `url(${this.props.image})`;
|
if (this.props.image) styleFigure.backgroundImage = `url(${this.props.image})`;
|
||||||
if (this.props.color) headingStyle.backgroundColor = this.props.color;
|
if (this.props.color) {
|
||||||
|
styleFigure.backgroundColor = this.props.color;
|
||||||
|
styleOverflow.backgroundColor = this.props.color;
|
||||||
|
}
|
||||||
|
|
||||||
if (this.props.title || this.props.image) {
|
if (this.props.title || this.props.image) {
|
||||||
return (
|
return (
|
||||||
<figure className={style.figure} style={headingStyle}>
|
<figure className={style.figure} style={styleFigure}>
|
||||||
{ this.props.subtitle ? <small>{this.props.subtitle}</small> : null }
|
{ this.props.subtitle ? <small>{this.props.subtitle}</small> : null }
|
||||||
{ this.props.title ? <h2>{this.props.title}</h2> : null }
|
{ this.props.title ? <h5>{this.props.title}</h5> : null }
|
||||||
|
{ this.props.color ? <div className={style.overflow} style={styleOverflow}></div> : null }
|
||||||
</figure>
|
</figure>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
renderActions () {
|
||||||
|
if (this.props.actions) {
|
||||||
|
return (
|
||||||
|
<Navigation className={style.navigation} actions={this.props.actions} />
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
let className = `${style.root} ${this.props.className}`;
|
let className = `${style.root} ${this.props.className}`;
|
||||||
if (this.props.type) className += ` ${this.props.type}`;
|
if (this.props.type) className += ` ${style[this.props.type]}`;
|
||||||
if (this.props.onClick) className += ' touch';
|
if (this.props.onClick) className += ` ${style.touch}`;
|
||||||
if (this.props.image) className += ' image';
|
if (this.props.image || this.props.color) className += ` ${style.contrast}`;
|
||||||
if (this.props.color) className += ' color';
|
if (this.props.color) className += ` ${style.color}`;
|
||||||
if (this.state.loading) className += ' loading';
|
if (this.state.loading) className += ` ${style.loading}`;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div data-react-toolbox='card' className={className} onMouseDown={this.onClick}>
|
<div
|
||||||
{ this.renderHeading() }
|
data-react-toolbox='card'
|
||||||
{ this.props.text ? <p>{this.props.text}</p> : null }
|
data-flex='vertical grow'
|
||||||
{ this.props.legend ? <small>{this.props.legend}</small> : null}
|
data-react-toolbox='card'
|
||||||
{ this.props.actions ? <Navigation className={style.navigation} actions={this.props.actions} /> : null }
|
className={className}
|
||||||
{ <Ripple ref="ripple" className={style.ripple} loading={this.state.loading} /> }
|
onMouseDown={this.handleMouseDown}
|
||||||
|
>
|
||||||
|
{ this.renderTitle() }
|
||||||
|
{ this.props.text ? <p className={style.text}>{this.props.text}</p> : null }
|
||||||
|
{ this.renderActions() }
|
||||||
|
<Ripple
|
||||||
|
ref='ripple'
|
||||||
|
className={style.ripple}
|
||||||
|
loading={this.state.loading}
|
||||||
|
spread={2.5}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
|
@ -0,0 +1,129 @@
|
||||||
|
@import "../variables";
|
||||||
|
@import "../mixins";
|
||||||
|
|
||||||
|
$card-color-white: unquote("rgb(#{$color-white})") !default;
|
||||||
|
$card-title-height: 17.6 * $unit;
|
||||||
|
$card-width-normal: 32 * $unit;
|
||||||
|
$card-width-large: 51.2 * $unit;
|
||||||
|
$card-text-overlay: unquote("rgba(#{$color-black}, 0.2)");
|
||||||
|
|
||||||
|
.figure {
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
min-height: $card-title-height;
|
||||||
|
flex-direction: column;
|
||||||
|
background-position: center center;
|
||||||
|
background-size: cover;
|
||||||
|
justify-content: flex-end;
|
||||||
|
|
||||||
|
> *:not(.overflow) {
|
||||||
|
z-index: 1;
|
||||||
|
font-weight: $font-weight-normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
> .overflow {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
z-index: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
opacity: .75;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.text {
|
||||||
|
font-size: $font-size-small;
|
||||||
|
line-height: 1.8 * $unit;
|
||||||
|
color: $color-text-secondary;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navigation {
|
||||||
|
$offset: ($offset / 2);
|
||||||
|
padding: $offset;
|
||||||
|
|
||||||
|
> * {
|
||||||
|
min-width: 0;
|
||||||
|
padding-right: $offset;
|
||||||
|
padding-left: $offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ripple {
|
||||||
|
background-color: $color-text-secondary;
|
||||||
|
}
|
||||||
|
|
||||||
|
.root {
|
||||||
|
@include shadow-2dp();
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
width: $card-width-normal;
|
||||||
|
flex-direction: column;
|
||||||
|
overflow: hidden;
|
||||||
|
vertical-align: top;
|
||||||
|
background: $color-background;
|
||||||
|
|
||||||
|
// -- Children
|
||||||
|
> *:not(.navigation) {
|
||||||
|
padding: $offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:not(.color) > *:not(.figure), > *:not(:last-child) {
|
||||||
|
box-shadow: 0 1px $color-divider;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.touch {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contrast {
|
||||||
|
.figure {
|
||||||
|
color: $card-color-white;
|
||||||
|
text-shadow: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ripple {
|
||||||
|
background-color: $card-color-white;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.loading {
|
||||||
|
pointer-events: none;
|
||||||
|
cursor: none;
|
||||||
|
filter: grayscale(100%);
|
||||||
|
|
||||||
|
.ripple {
|
||||||
|
@include ripple-loading(cardloading, 2 * $card-width-normal, 2 * $card-width-normal);
|
||||||
|
width: 2 * $card-width-normal;
|
||||||
|
height: 2 * $card-width-normal;
|
||||||
|
animation-name: cardloading;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.image {
|
||||||
|
&, .figure {
|
||||||
|
height: $card-width-normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.figure {
|
||||||
|
padding: 0;
|
||||||
|
|
||||||
|
> h5 {
|
||||||
|
padding: $offset;
|
||||||
|
font-size: $font-size-small;
|
||||||
|
font-weight: $font-weight-bold;
|
||||||
|
background-color: $card-text-overlay;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.event {
|
||||||
|
.figure {
|
||||||
|
justify-content: flex-start;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.wide {
|
||||||
|
width: $card-width-large;
|
||||||
|
}
|
|
@ -1,70 +0,0 @@
|
||||||
@import '../constants'
|
|
||||||
|
|
||||||
SIZE = (5 * UNIT)
|
|
||||||
OFFSET = (SPACE / 1.25)
|
|
||||||
|
|
||||||
:local(.navigation)
|
|
||||||
padding : OFFSET = (OFFSET / 2)
|
|
||||||
> *
|
|
||||||
padding-left : OFFSET
|
|
||||||
padding-right : OFFSET
|
|
||||||
box-shadow : none !important
|
|
||||||
&:hover
|
|
||||||
background-color : rgba(0,0,0,0.1) !important
|
|
||||||
|
|
||||||
:local(.figure)
|
|
||||||
display-flex()
|
|
||||||
flex-direction : column
|
|
||||||
justify-content : flex-end
|
|
||||||
flex-grow : 2
|
|
||||||
min-height : (SIZE / 2)
|
|
||||||
background-size : cover
|
|
||||||
> *
|
|
||||||
font-weight : FONT_WEIGHT_NORMAL
|
|
||||||
|
|
||||||
:local(.root)
|
|
||||||
display-flex()
|
|
||||||
flex-direction column
|
|
||||||
position : relative
|
|
||||||
overflow : hidden
|
|
||||||
width : SIZE
|
|
||||||
box-shadow : ZDEPTH_SHADOW_1
|
|
||||||
background : WHITE
|
|
||||||
|
|
||||||
// -- Children
|
|
||||||
> *:not(:local(.ripple)):not(:local(.navigation))
|
|
||||||
padding : OFFSET
|
|
||||||
&:not(.color):not(.image) > :local(.ripple)
|
|
||||||
background-color : red
|
|
||||||
&:not(.color) > *:not(figure), > *:not(:last-child)
|
|
||||||
box-shadow : 0 1px darken(BACKGROUND, 5%)
|
|
||||||
> :local(.figure)
|
|
||||||
|
|
||||||
// -- Overrides
|
|
||||||
&.touch
|
|
||||||
cursor : pointer
|
|
||||||
&:hover, &:active
|
|
||||||
box-shadow : ZDEPTH_SHADOW_2
|
|
||||||
&.image > :local(.figure)
|
|
||||||
text-shadow : ZDEPTH_SHADOW_1
|
|
||||||
&.image, &.color
|
|
||||||
> :local(.figure)
|
|
||||||
color : WHITE
|
|
||||||
&.loading
|
|
||||||
cursor : none
|
|
||||||
pointer-events : none
|
|
||||||
-webkit-filter : grayscale(100%)
|
|
||||||
&, &:hover
|
|
||||||
box-shadow : 0 0 0 1px DIVIDER
|
|
||||||
:local(.ripple)
|
|
||||||
width : SIZE = (SIZE * 2)
|
|
||||||
height : SIZE
|
|
||||||
&.small > :local(.figure)
|
|
||||||
min-height : 0px
|
|
||||||
&.square
|
|
||||||
height : SIZE
|
|
||||||
&.wide
|
|
||||||
width : (SIZE * 2)
|
|
||||||
|
|
||||||
:local(.ripple)
|
|
||||||
background-color: #888
|
|
|
@ -0,0 +1,99 @@
|
||||||
|
import React from 'react';
|
||||||
|
import PureRenderMixin from 'react-addons-pure-render-mixin';
|
||||||
|
import Ripple from '../ripple';
|
||||||
|
import style from './style';
|
||||||
|
import events from '../utils/events';
|
||||||
|
|
||||||
|
export default React.createClass({
|
||||||
|
mixins: [PureRenderMixin],
|
||||||
|
|
||||||
|
displayName: 'Checkbox',
|
||||||
|
|
||||||
|
propTypes: {
|
||||||
|
checked: React.PropTypes.bool,
|
||||||
|
className: React.PropTypes.string,
|
||||||
|
disabled: React.PropTypes.bool,
|
||||||
|
label: React.PropTypes.string,
|
||||||
|
name: React.PropTypes.string,
|
||||||
|
onBlur: React.PropTypes.func,
|
||||||
|
onChange: React.PropTypes.func,
|
||||||
|
onFocus: React.PropTypes.func
|
||||||
|
},
|
||||||
|
|
||||||
|
getDefaultProps () {
|
||||||
|
return {
|
||||||
|
checked: false,
|
||||||
|
className: '',
|
||||||
|
disabled: false
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
getInitialState () {
|
||||||
|
return { checked: this.props.checked };
|
||||||
|
},
|
||||||
|
|
||||||
|
handleChange (event) {
|
||||||
|
this.setState({checked: !this.state.checked}, () => {
|
||||||
|
if (this.props.onChange) this.props.onChange(event, this);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
handleClick (event) {
|
||||||
|
events.pauseEvent(event);
|
||||||
|
if (!this.props.disabled) this.handleChange(event);
|
||||||
|
},
|
||||||
|
|
||||||
|
handleMouseDown (event) {
|
||||||
|
if (!this.props.disabled) this.refs.ripple.start(event);
|
||||||
|
},
|
||||||
|
|
||||||
|
handleInputClick (event) {
|
||||||
|
events.pauseEvent(event);
|
||||||
|
},
|
||||||
|
|
||||||
|
render () {
|
||||||
|
let fieldClassName = style.field;
|
||||||
|
let checkboxClassName = style.check;
|
||||||
|
if (this.props.disabled) fieldClassName += ` ${style.disabled}`;
|
||||||
|
if (this.props.className) fieldClassName += ` ${this.props.className}`;
|
||||||
|
if (this.state.checked) checkboxClassName += ` ${style.checked}`;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<label
|
||||||
|
data-react-toolbox='checkbox'
|
||||||
|
className={fieldClassName}
|
||||||
|
onClick={this.handleClick}
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
{...this.props}
|
||||||
|
ref='input'
|
||||||
|
type='checkbox'
|
||||||
|
checked={this.state.checked}
|
||||||
|
className={style.input}
|
||||||
|
onChange={this.handleChange}
|
||||||
|
onClick={this.handleInputClick}
|
||||||
|
/>
|
||||||
|
<span role='checkbox' className={checkboxClassName} onMouseDown={this.handleMouseDown}>
|
||||||
|
<Ripple ref='ripple' role='ripple' className={style.ripple} spread={3} centered />
|
||||||
|
</span>
|
||||||
|
{ this.props.label ? <span className={style.text}>{this.props.label}</span> : null }
|
||||||
|
</label>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
blur () {
|
||||||
|
this.refs.input.blur();
|
||||||
|
},
|
||||||
|
|
||||||
|
focus () {
|
||||||
|
this.refs.input.focus();
|
||||||
|
},
|
||||||
|
|
||||||
|
getValue () {
|
||||||
|
return this.state.checked;
|
||||||
|
},
|
||||||
|
|
||||||
|
setValue (value) {
|
||||||
|
this.setState({checked: value});
|
||||||
|
}
|
||||||
|
});
|
|
@ -0,0 +1,135 @@
|
||||||
|
@import "../variables";
|
||||||
|
|
||||||
|
$checkbox-total-height: 1.8 * $unit;
|
||||||
|
$checkbox-size: 1.8 * $unit;
|
||||||
|
$checkbox-transition-duration: .2s;
|
||||||
|
$checkbox-focus-size: $checkbox-size * 2.3;
|
||||||
|
$checkbox-color: unquote("rgb(#{$color-primary})") !default;
|
||||||
|
$checkbox-text-color: unquote("rgb(#{$color-black})") !default;
|
||||||
|
$checkbox-disabled-color: unquote("rgba(#{$color-black}, 0.26)") !default;
|
||||||
|
$check-focus-color: unquote("rgba(#{$color-black}, 0.1)") !default;
|
||||||
|
$checked-focus-color: unquote("rgba(#{$color-primary}, 0.26)") !default;
|
||||||
|
|
||||||
|
.field {
|
||||||
|
position: relative;
|
||||||
|
display: block;
|
||||||
|
height: $checkbox-size;
|
||||||
|
margin-bottom: 1.5 * $unit;
|
||||||
|
white-space: nowrap;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text {
|
||||||
|
display: inline-block;
|
||||||
|
padding-left: $unit;
|
||||||
|
font-size: 1.4 * $unit;
|
||||||
|
line-height: $checkbox-size;
|
||||||
|
color: $checkbox-text-color;
|
||||||
|
white-space: nowrap;
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input {
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
opacity: 0;
|
||||||
|
|
||||||
|
&:focus:not(&:active) + .check {
|
||||||
|
&:before {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
z-index: $z-index-low;
|
||||||
|
width: $checkbox-focus-size;
|
||||||
|
height: $checkbox-focus-size;
|
||||||
|
margin-top: - $checkbox-focus-size / 2;
|
||||||
|
margin-left: - $checkbox-focus-size / 2;
|
||||||
|
pointer-events: none;
|
||||||
|
content: "";
|
||||||
|
background-color: $check-focus-color;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.checked:before {
|
||||||
|
background-color: $checked-focus-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.check {
|
||||||
|
position: relative;
|
||||||
|
display: inline-block;
|
||||||
|
width: $checkbox-size;
|
||||||
|
height: $checkbox-size;
|
||||||
|
vertical-align: top;
|
||||||
|
cursor: pointer;
|
||||||
|
border-color: $checkbox-text-color;
|
||||||
|
border-style: solid;
|
||||||
|
border-width: 2px;
|
||||||
|
border-radius: 2px;
|
||||||
|
transition-timing-function: $animation-curve-default;
|
||||||
|
transition-duration: $checkbox-transition-duration;
|
||||||
|
transition-property: background-color;
|
||||||
|
|
||||||
|
&.checked {
|
||||||
|
background-color: $checkbox-color;
|
||||||
|
border-color: $checkbox-color;
|
||||||
|
|
||||||
|
&:after {
|
||||||
|
position: absolute;
|
||||||
|
top: -.1 * $unit;
|
||||||
|
left: .4 * $unit;
|
||||||
|
width: .7 * $unit;
|
||||||
|
height: 1.2 * $unit;
|
||||||
|
content: "";
|
||||||
|
border-color: #fff;
|
||||||
|
border-style: solid;
|
||||||
|
border-top: 0;
|
||||||
|
border-right-width: 2px;
|
||||||
|
border-bottom-width: 2px;
|
||||||
|
border-left: 0;
|
||||||
|
transform: rotate(45deg);
|
||||||
|
animation: checkmark-expand 140ms ease-out forwards;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ripple {
|
||||||
|
background-color: $checkbox-color;
|
||||||
|
opacity: .3;
|
||||||
|
transition-duration: 650ms;
|
||||||
|
}
|
||||||
|
|
||||||
|
.disabled {
|
||||||
|
> .text {
|
||||||
|
color: $checkbox-disabled-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
> .check {
|
||||||
|
cursor: auto;
|
||||||
|
border-color: $checkbox-disabled-color;
|
||||||
|
|
||||||
|
&.checked {
|
||||||
|
cursor: auto;
|
||||||
|
background-color: $checkbox-disabled-color;
|
||||||
|
border-color: transparent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes checkmark-expand {
|
||||||
|
0% {
|
||||||
|
top: .9 * $unit;
|
||||||
|
left: .6 * $unit;
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
top: -.1 * $unit;
|
||||||
|
left: .4 * $unit;
|
||||||
|
width: .7 * $unit;
|
||||||
|
height: 1.2 * $unit;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,10 +1,9 @@
|
||||||
/* global React */
|
import React from 'react';
|
||||||
|
import PureRenderMixin from 'react-addons-pure-render-mixin';
|
||||||
import { addons } from 'react/addons';
|
import style from './style';
|
||||||
import css from './style';
|
|
||||||
|
|
||||||
export default React.createClass({
|
export default React.createClass({
|
||||||
mixins: [addons.PureRenderMixin],
|
mixins: [PureRenderMixin],
|
||||||
|
|
||||||
displayName: 'Face',
|
displayName: 'Face',
|
||||||
|
|
||||||
|
@ -33,10 +32,14 @@ export default React.createClass({
|
||||||
},
|
},
|
||||||
|
|
||||||
renderNumber (number, idx) {
|
renderNumber (number, idx) {
|
||||||
|
let className = style.number;
|
||||||
|
if (number === this.props.active) className += ` ${style.active}`;
|
||||||
return (
|
return (
|
||||||
<span className={css.number + (number === this.props.active ? ' active' : '')}
|
<span
|
||||||
style={this.numberStyle(this.props.radius - this.props.spacing, idx + 1)}
|
className={className}
|
||||||
key={number}>
|
style={this.numberStyle(this.props.radius - this.props.spacing, idx + 1)}
|
||||||
|
key={number}
|
||||||
|
>
|
||||||
{ this.props.twoDigits ? ('0' + number).slice(-2) : number }
|
{ this.props.twoDigits ? ('0' + number).slice(-2) : number }
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
|
@ -44,11 +47,13 @@ export default React.createClass({
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
return (
|
return (
|
||||||
<div ref="root"
|
<div
|
||||||
className={css.face}
|
ref="root"
|
||||||
onTouchStart={this.props.onTouchStart}
|
className={style.face}
|
||||||
onMouseDown={this.props.onMouseDown}
|
onTouchStart={this.props.onTouchStart}
|
||||||
style={this.faceStyle()}>
|
onMouseDown={this.props.onMouseDown}
|
||||||
|
style={this.faceStyle()}
|
||||||
|
>
|
||||||
{ this.props.numbers.map(this.renderNumber)}
|
{ this.props.numbers.map(this.renderNumber)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
/* global React */
|
import React from 'react';
|
||||||
|
import PureRenderMixin from 'react-addons-pure-render-mixin';
|
||||||
import { addons } from 'react/addons';
|
import style from './style';
|
||||||
import css from './style';
|
|
||||||
import utils from '../utils';
|
import utils from '../utils';
|
||||||
|
|
||||||
export default React.createClass({
|
export default React.createClass({
|
||||||
mixins: [addons.PureRenderMixin],
|
mixins: [PureRenderMixin],
|
||||||
|
|
||||||
displayName: 'Hand',
|
displayName: 'Hand',
|
||||||
|
|
||||||
|
@ -30,7 +29,7 @@ export default React.createClass({
|
||||||
},
|
},
|
||||||
|
|
||||||
componentDidMount () {
|
componentDidMount () {
|
||||||
this.setState({knobWidth: this.refs.knob.getDOMNode().offsetWidth});
|
this.setState({knobWidth: this.refs.knob.offsetWidth});
|
||||||
},
|
},
|
||||||
|
|
||||||
getMouseEventMap () {
|
getMouseEventMap () {
|
||||||
|
@ -100,14 +99,15 @@ export default React.createClass({
|
||||||
},
|
},
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
let style = utils.prefixer({
|
const className = `${style.hand} ${this.props.className}`;
|
||||||
|
let handStyle = utils.prefixer({
|
||||||
height: this.props.length - this.state.knobWidth / 2,
|
height: this.props.length - this.state.knobWidth / 2,
|
||||||
transform: `rotate(${this.props.angle}deg)`
|
transform: `rotate(${this.props.angle}deg)`
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={css.hand + ' ' + this.props.className} style={style}>
|
<div className={className} style={handStyle}>
|
||||||
<div ref='knob' className={css.knob}></div>
|
<div ref='knob' className={style.knob}></div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
/* global React */
|
import React from 'react';
|
||||||
|
import PureRenderMixin from 'react-addons-pure-render-mixin';
|
||||||
import { addons } from 'react/addons';
|
|
||||||
import utils from '../utils';
|
import utils from '../utils';
|
||||||
import Face from './face';
|
import Face from './face';
|
||||||
import Hand from './hand';
|
import Hand from './hand';
|
||||||
|
|
||||||
const outerNumbers = [0, ...utils.range(13, 24)];
|
const outerNumbers = [0, ...utils.range(13, 24)];
|
||||||
const innerNumbers = [12, ...utils.range(1, 12)];
|
const innerNumbers = [12, ...utils.range(1, 12)];
|
||||||
|
const innerSpacing = 1.7;
|
||||||
const step = 360 / 12;
|
const step = 360 / 12;
|
||||||
|
|
||||||
export default React.createClass({
|
export default React.createClass({
|
||||||
mixins: [addons.PureRenderMixin],
|
mixins: [PureRenderMixin],
|
||||||
|
|
||||||
displayName: 'Hours',
|
displayName: 'Hours',
|
||||||
|
|
||||||
|
@ -28,10 +28,13 @@ export default React.createClass({
|
||||||
},
|
},
|
||||||
|
|
||||||
onHandMove (degrees, radius) {
|
onHandMove (degrees, radius) {
|
||||||
let currentInner = radius < this.props.radius - this.props.spacing * 2;
|
let currentInner = radius < this.props.radius - this.props.spacing * innerSpacing;
|
||||||
this.props.onChange(this.valueFromDegrees(degrees));
|
|
||||||
if (this.props.format === '24hr' && this.state.inner !== currentInner) {
|
if (this.props.format === '24hr' && this.state.inner !== currentInner) {
|
||||||
this.setState({inner: currentInner});
|
this.setState({inner: currentInner}, () => {
|
||||||
|
this.props.onChange(this.valueFromDegrees(degrees));
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.props.onChange(this.valueFromDegrees(degrees));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -60,7 +63,8 @@ export default React.createClass({
|
||||||
numbers={innerNumbers}
|
numbers={innerNumbers}
|
||||||
spacing={this.props.spacing}
|
spacing={this.props.spacing}
|
||||||
radius={innerRadius}
|
radius={innerRadius}
|
||||||
active={this.props.selected} />
|
active={this.props.selected}
|
||||||
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -78,15 +82,17 @@ export default React.createClass({
|
||||||
spacing={spacing}
|
spacing={spacing}
|
||||||
radius={radius}
|
radius={radius}
|
||||||
twoDigits={is24hr}
|
twoDigits={is24hr}
|
||||||
active={is24hr ? selected : (selected % 12 || 12)} />
|
active={is24hr ? selected : (selected % 12 || 12)}
|
||||||
{ this.renderInnerFace(radius - spacing * 2) }
|
/>
|
||||||
|
{ this.renderInnerFace(radius - spacing * innerSpacing) }
|
||||||
<Hand ref='hand'
|
<Hand ref='hand'
|
||||||
angle={selected * step}
|
angle={selected * step}
|
||||||
length={(this.state.inner ? radius - spacing * 2 : radius) - spacing}
|
length={(this.state.inner ? radius - spacing * innerSpacing : radius) - spacing}
|
||||||
onMove={this.onHandMove}
|
onMove={this.onHandMove}
|
||||||
onMoved={onHandMoved}
|
onMoved={onHandMoved}
|
||||||
origin={center}
|
origin={center}
|
||||||
step={step} />
|
step={step}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,12 @@
|
||||||
/* global React */
|
import React from 'react';
|
||||||
|
import PureRenderMixin from 'react-addons-pure-render-mixin';
|
||||||
import { addons } from 'react/addons';
|
import style from './style';
|
||||||
import css from './style';
|
|
||||||
import time from '../utils/time';
|
import time from '../utils/time';
|
||||||
import Hours from './hours';
|
import Hours from './hours';
|
||||||
import Minutes from './minutes';
|
import Minutes from './minutes';
|
||||||
|
|
||||||
export default React.createClass({
|
export default React.createClass({
|
||||||
mixins: [addons.PureRenderMixin],
|
mixins: [PureRenderMixin],
|
||||||
|
|
||||||
displayName: 'Clock',
|
displayName: 'Clock',
|
||||||
|
|
||||||
|
@ -80,7 +79,7 @@ export default React.createClass({
|
||||||
},
|
},
|
||||||
|
|
||||||
calculateShape () {
|
calculateShape () {
|
||||||
let { top, left, width } = this.refs.wrapper.getDOMNode().getBoundingClientRect();
|
let { top, left, width } = this.refs.wrapper.getBoundingClientRect();
|
||||||
this.setState({
|
this.setState({
|
||||||
center: { x: left + width / 2, y: top + width / 2 },
|
center: { x: left + width / 2, y: top + width / 2 },
|
||||||
radius: width / 2
|
radius: width / 2
|
||||||
|
@ -95,7 +94,8 @@ export default React.createClass({
|
||||||
onChange={this.onHourChange}
|
onChange={this.onHourChange}
|
||||||
radius={this.state.radius}
|
radius={this.state.radius}
|
||||||
selected={this.state.time.getHours()}
|
selected={this.state.time.getHours()}
|
||||||
spacing={this.state.radius * 0.16} />
|
spacing={this.state.radius * 0.18}
|
||||||
|
/>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -106,14 +106,15 @@ export default React.createClass({
|
||||||
onChange={this.onMinuteChange}
|
onChange={this.onMinuteChange}
|
||||||
radius={this.state.radius}
|
radius={this.state.radius}
|
||||||
selected={this.state.time.getMinutes()}
|
selected={this.state.time.getMinutes()}
|
||||||
spacing={this.state.radius * 0.16} />
|
spacing={this.state.radius * 0.18}
|
||||||
|
/>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
return (
|
return (
|
||||||
<div className={css.root}>
|
<div data-react-toolbox='clock' className={style.root}>
|
||||||
<div ref="wrapper" className={css.wrapper} style={{height: this.state.radius * 2}}>
|
<div ref="wrapper" className={style.wrapper} style={{height: this.state.radius * 2}}>
|
||||||
{ this.props.display === 'hours' ? this.renderHours() : '' }
|
{ this.props.display === 'hours' ? this.renderHours() : '' }
|
||||||
{ this.props.display === 'minutes' ? this.renderMinutes() : '' }
|
{ this.props.display === 'minutes' ? this.renderMinutes() : '' }
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/* global React */
|
import React from 'react';
|
||||||
|
import PureRenderMixin from 'react-addons-pure-render-mixin';
|
||||||
import { addons } from 'react/addons';
|
|
||||||
import utils from '../utils';
|
import utils from '../utils';
|
||||||
|
import style from './style';
|
||||||
import Face from './face';
|
import Face from './face';
|
||||||
import Hand from './hand';
|
import Hand from './hand';
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ const minutes = utils.range(0, 60, 5);
|
||||||
const step = 360 / 60;
|
const step = 360 / 60;
|
||||||
|
|
||||||
export default React.createClass({
|
export default React.createClass({
|
||||||
mixins: [addons.PureRenderMixin],
|
mixins: [PureRenderMixin],
|
||||||
|
|
||||||
displayName: 'Minutes',
|
displayName: 'Minutes',
|
||||||
|
|
||||||
|
@ -47,14 +47,16 @@ export default React.createClass({
|
||||||
spacing={this.props.spacing}
|
spacing={this.props.spacing}
|
||||||
radius={this.props.radius}
|
radius={this.props.radius}
|
||||||
twoDigits={true}
|
twoDigits={true}
|
||||||
active={this.props.selected} />
|
active={this.props.selected}
|
||||||
|
/>
|
||||||
<Hand ref='hand'
|
<Hand ref='hand'
|
||||||
className={minutes.indexOf(this.props.selected) === -1 ? 'smallKnob' : ''}
|
className={minutes.indexOf(this.props.selected) === -1 ? style.small : ''}
|
||||||
angle={this.props.selected * step}
|
angle={this.props.selected * step}
|
||||||
length={this.props.radius - this.props.spacing}
|
length={this.props.radius - this.props.spacing}
|
||||||
onMove={this.onHandMove}
|
onMove={this.onHandMove}
|
||||||
origin={this.props.center}
|
origin={this.props.center}
|
||||||
step={step} />
|
step={step}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,113 @@
|
||||||
|
@import "../variables";
|
||||||
|
|
||||||
|
$clock-primary: $color-primary;
|
||||||
|
$clock-primary-contrast: $color-primary-contrast;
|
||||||
|
$clock-primary-dark: $color-primary-dark;
|
||||||
|
$clock-primary-color: unquote("rgb(#{$clock-primary})") !default;
|
||||||
|
$clock-primary-hover-color: unquote("rgba(#{$clock-primary}, 0.20)") !default;
|
||||||
|
$clock-primary-contrast-color: unquote("rgb(#{$clock-primary-contrast})") !default;
|
||||||
|
$clock-primary-dark-color: unquote("rgb(#{$clock-primary-dark})") !default;
|
||||||
|
$clock-number-size: 2 * $unit;
|
||||||
|
$clock-hand-width: .4 * $unit;
|
||||||
|
$clock-hand-dot-size: 1 * $unit;
|
||||||
|
$clock-knob-size: 3.4 * $unit;
|
||||||
|
$clock-knob-small-size: 1.2 * $unit;
|
||||||
|
|
||||||
|
.root {
|
||||||
|
padding: 1.5 * $unit 2 * $unit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wrapper {
|
||||||
|
position: relative;
|
||||||
|
background-color: $color-divider;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.face {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
z-index: $z-index-high;
|
||||||
|
cursor: pointer;
|
||||||
|
border-radius: 50%;
|
||||||
|
transform: translateX(-50%) translateY(-50%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.number {
|
||||||
|
position: relative;
|
||||||
|
width: $clock-number-size;
|
||||||
|
height: $clock-number-size;
|
||||||
|
margin-top: - $clock-number-size / 2;
|
||||||
|
margin-left: - $clock-number-size / 2;
|
||||||
|
text-align: center;
|
||||||
|
pointer-events: none;
|
||||||
|
user-select: none;
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
color: $clock-primary-contrast-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.hand {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 50%;
|
||||||
|
left: 50%;
|
||||||
|
display: block;
|
||||||
|
width: $clock-hand-width;
|
||||||
|
margin-left: - $clock-hand-width / 2;
|
||||||
|
background-color: $clock-primary-color;
|
||||||
|
transform-origin: 50% 100%;
|
||||||
|
|
||||||
|
&:before {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
left: 50%;
|
||||||
|
width: $clock-hand-dot-size;
|
||||||
|
height: $clock-hand-dot-size;
|
||||||
|
margin-bottom: - $clock-hand-dot-size / 2;
|
||||||
|
margin-left: - $clock-hand-dot-size / 2;
|
||||||
|
content: "";
|
||||||
|
background-color: $clock-primary-color;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.small > .knob {
|
||||||
|
background-color: $clock-primary-hover-color;
|
||||||
|
|
||||||
|
&:after {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
width: $clock-knob-small-size;
|
||||||
|
height: $clock-knob-small-size;
|
||||||
|
margin-top: - $clock-knob-small-size / 2;
|
||||||
|
margin-left: - $clock-knob-small-size / 2;
|
||||||
|
content: "";
|
||||||
|
background: $clock-primary-color;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:before {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
left: 50%;
|
||||||
|
width: $clock-hand-width;
|
||||||
|
height: $clock-knob-size - $clock-knob-small-size;
|
||||||
|
margin-left: - $clock-hand-width / 2;
|
||||||
|
content: "";
|
||||||
|
background: $clock-primary-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.knob {
|
||||||
|
position: absolute;
|
||||||
|
top: - $clock-knob-size;
|
||||||
|
left: 50%;
|
||||||
|
width: $clock-knob-size;
|
||||||
|
height: $clock-knob-size;
|
||||||
|
margin-left: - $clock-knob-size / 2;
|
||||||
|
cursor: pointer;
|
||||||
|
background-color: $clock-primary-color;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
|
@ -1,98 +0,0 @@
|
||||||
@import '../constants'
|
|
||||||
|
|
||||||
NUMBER_SIZE = 20px
|
|
||||||
HAND_WIDTH = 4px
|
|
||||||
HAND_DOT_SIZE = 10px
|
|
||||||
KNOB_SIZE = 34px
|
|
||||||
SMALL_KNOB_SIZE = 12px
|
|
||||||
|
|
||||||
:local(.root)
|
|
||||||
padding : 15px
|
|
||||||
|
|
||||||
:local(.wrapper)
|
|
||||||
background-color : DIVIDER
|
|
||||||
border-radius : 50%
|
|
||||||
position : relative
|
|
||||||
|
|
||||||
:local(.face)
|
|
||||||
border-radius : 50%
|
|
||||||
cursor : pointer
|
|
||||||
position : relative
|
|
||||||
z-index : Z_INDEX_HIGH
|
|
||||||
|
|
||||||
:local(.number)
|
|
||||||
height : NUMBER_SIZE
|
|
||||||
margin-left : -(NUMBER_SIZE/2)
|
|
||||||
margin-top : -(NUMBER_SIZE/2)
|
|
||||||
pointer-events : none
|
|
||||||
position : relative
|
|
||||||
text-align : center
|
|
||||||
user-select : none
|
|
||||||
width : NUMBER_SIZE
|
|
||||||
|
|
||||||
&.active
|
|
||||||
color : WHITE
|
|
||||||
|
|
||||||
:local(.face)
|
|
||||||
position : absolute
|
|
||||||
top : 50%
|
|
||||||
left : 50%
|
|
||||||
transform : translateX(-50%) translateY(-50%)
|
|
||||||
|
|
||||||
:local(.hand)
|
|
||||||
background-color : ACCENT
|
|
||||||
bottom : 50%
|
|
||||||
display : block
|
|
||||||
left : 50%
|
|
||||||
margin-left : -(HAND_WIDTH/2)
|
|
||||||
position : absolute
|
|
||||||
transform-origin : 50% 100%
|
|
||||||
width : HAND_WIDTH
|
|
||||||
|
|
||||||
&:before
|
|
||||||
background-color : ACCENT
|
|
||||||
border-radius : 50%
|
|
||||||
bottom : 0
|
|
||||||
content : ''
|
|
||||||
height : HAND_DOT_SIZE
|
|
||||||
left : 50%
|
|
||||||
margin-bottom : -(HAND_DOT_SIZE/2)
|
|
||||||
margin-left : -(HAND_DOT_SIZE/2)
|
|
||||||
position : absolute
|
|
||||||
width : HAND_DOT_SIZE
|
|
||||||
|
|
||||||
&.smallKnob :local(.knob)
|
|
||||||
background-color: lighten(ACCENT, 70%)
|
|
||||||
|
|
||||||
&:after
|
|
||||||
background : ACCENT
|
|
||||||
border-radius : 50%
|
|
||||||
content : ''
|
|
||||||
height : SMALL_KNOB_SIZE
|
|
||||||
left : 50%
|
|
||||||
margin-left : -(SMALL_KNOB_SIZE/2)
|
|
||||||
margin-top : -(SMALL_KNOB_SIZE/2)
|
|
||||||
position : absolute
|
|
||||||
top : 50%
|
|
||||||
width : SMALL_KNOB_SIZE
|
|
||||||
|
|
||||||
&:before
|
|
||||||
background : ACCENT
|
|
||||||
bottom : 0
|
|
||||||
content : ''
|
|
||||||
height : KNOB_SIZE - SMALL_KNOB_SIZE
|
|
||||||
left : 50%
|
|
||||||
margin-left : -(HAND_WIDTH/2)
|
|
||||||
position : absolute
|
|
||||||
width : HAND_WIDTH
|
|
||||||
|
|
||||||
:local(.knob)
|
|
||||||
background-color : ACCENT
|
|
||||||
border-radius : 50%
|
|
||||||
cursor : pointer
|
|
||||||
height : KNOB_SIZE
|
|
||||||
left : 50%
|
|
||||||
margin-left : -(KNOB_SIZE/2)
|
|
||||||
position : absolute
|
|
||||||
top : -(KNOB_SIZE)
|
|
||||||
width : KNOB_SIZE
|
|
|
@ -0,0 +1,163 @@
|
||||||
|
//-- Color definitions taken from Material Design Lite
|
||||||
|
$palette-indigo:
|
||||||
|
"232,234,246"
|
||||||
|
"197,202,233"
|
||||||
|
"159,168,218"
|
||||||
|
"121,134,203"
|
||||||
|
"92,107,192"
|
||||||
|
"63,81,181"
|
||||||
|
"57,73,171"
|
||||||
|
"48,63,159"
|
||||||
|
"40,53,147"
|
||||||
|
"26,35,126"
|
||||||
|
"140,158,255"
|
||||||
|
"83,109,254"
|
||||||
|
"61,90,254"
|
||||||
|
"48,79,254";
|
||||||
|
|
||||||
|
$palette-indigo-50: nth($palette-indigo, 1);
|
||||||
|
$palette-indigo-100: nth($palette-indigo, 2);
|
||||||
|
$palette-indigo-200: nth($palette-indigo, 3);
|
||||||
|
$palette-indigo-300: nth($palette-indigo, 4);
|
||||||
|
$palette-indigo-400: nth($palette-indigo, 5);
|
||||||
|
$palette-indigo-500: nth($palette-indigo, 6);
|
||||||
|
$palette-indigo-600: nth($palette-indigo, 7);
|
||||||
|
$palette-indigo-700: nth($palette-indigo, 8);
|
||||||
|
$palette-indigo-800: nth($palette-indigo, 9);
|
||||||
|
$palette-indigo-900: nth($palette-indigo, 10);
|
||||||
|
$palette-indigo-a100: nth($palette-indigo, 11);
|
||||||
|
$palette-indigo-a200: nth($palette-indigo, 12);
|
||||||
|
$palette-indigo-a400: nth($palette-indigo, 13);
|
||||||
|
$palette-indigo-a700: nth($palette-indigo, 14);
|
||||||
|
|
||||||
|
$palette-pink:
|
||||||
|
"252,228,236"
|
||||||
|
"248,187,208"
|
||||||
|
"244,143,177"
|
||||||
|
"240,98,146"
|
||||||
|
"236,64,122"
|
||||||
|
"233,30,99"
|
||||||
|
"216,27,96"
|
||||||
|
"194,24,91"
|
||||||
|
"173,20,87"
|
||||||
|
"136,14,79"
|
||||||
|
"255,128,171"
|
||||||
|
"255,64,129"
|
||||||
|
"245,0,87"
|
||||||
|
"197,17,98";
|
||||||
|
|
||||||
|
$palette-pink-50: nth($palette-pink, 1);
|
||||||
|
$palette-pink-100: nth($palette-pink, 2);
|
||||||
|
$palette-pink-200: nth($palette-pink, 3);
|
||||||
|
$palette-pink-300: nth($palette-pink, 4);
|
||||||
|
$palette-pink-400: nth($palette-pink, 5);
|
||||||
|
$palette-pink-500: nth($palette-pink, 6);
|
||||||
|
$palette-pink-600: nth($palette-pink, 7);
|
||||||
|
$palette-pink-700: nth($palette-pink, 8);
|
||||||
|
$palette-pink-800: nth($palette-pink, 9);
|
||||||
|
$palette-pink-900: nth($palette-pink, 10);
|
||||||
|
$palette-pink-a100: nth($palette-pink, 11);
|
||||||
|
$palette-pink-a200: nth($palette-pink, 12);
|
||||||
|
$palette-pink-a400: nth($palette-pink, 13);
|
||||||
|
$palette-pink-a700: nth($palette-pink, 14);
|
||||||
|
|
||||||
|
$palette-grey:
|
||||||
|
"250,250,250"
|
||||||
|
"245,245,245"
|
||||||
|
"238,238,238"
|
||||||
|
"224,224,224"
|
||||||
|
"189,189,189"
|
||||||
|
"158,158,158"
|
||||||
|
"117,117,117"
|
||||||
|
"97,97,97"
|
||||||
|
"66,66,66"
|
||||||
|
"33,33,33";
|
||||||
|
|
||||||
|
$palette-grey-50: nth($palette-grey, 1);
|
||||||
|
$palette-grey-100: nth($palette-grey, 2);
|
||||||
|
$palette-grey-200: nth($palette-grey, 3);
|
||||||
|
$palette-grey-300: nth($palette-grey, 4);
|
||||||
|
$palette-grey-400: nth($palette-grey, 5);
|
||||||
|
$palette-grey-500: nth($palette-grey, 6);
|
||||||
|
$palette-grey-600: nth($palette-grey, 7);
|
||||||
|
$palette-grey-700: nth($palette-grey, 8);
|
||||||
|
$palette-grey-800: nth($palette-grey, 9);
|
||||||
|
$palette-grey-900: nth($palette-grey, 10);
|
||||||
|
|
||||||
|
$palette-blue:
|
||||||
|
"227,242,253"
|
||||||
|
"187,222,251"
|
||||||
|
"144,202,249"
|
||||||
|
"100,181,246"
|
||||||
|
"66,165,245"
|
||||||
|
"33,150,243"
|
||||||
|
"30,136,229"
|
||||||
|
"25,118,210"
|
||||||
|
"21,101,192"
|
||||||
|
"13,71,161"
|
||||||
|
"130,177,255"
|
||||||
|
"68,138,255"
|
||||||
|
"41,121,255"
|
||||||
|
"41,98,255";
|
||||||
|
|
||||||
|
$palette-blue-50: nth($palette-blue, 1);
|
||||||
|
$palette-blue-100: nth($palette-blue, 2);
|
||||||
|
$palette-blue-200: nth($palette-blue, 3);
|
||||||
|
$palette-blue-300: nth($palette-blue, 4);
|
||||||
|
$palette-blue-400: nth($palette-blue, 5);
|
||||||
|
$palette-blue-500: nth($palette-blue, 6);
|
||||||
|
$palette-blue-600: nth($palette-blue, 7);
|
||||||
|
$palette-blue-700: nth($palette-blue, 8);
|
||||||
|
$palette-blue-800: nth($palette-blue, 9);
|
||||||
|
$palette-blue-900: nth($palette-blue, 10);
|
||||||
|
$palette-blue-a100: nth($palette-blue, 11);
|
||||||
|
$palette-blue-a200: nth($palette-blue, 12);
|
||||||
|
$palette-blue-a400: nth($palette-blue, 13);
|
||||||
|
$palette-blue-a700: nth($palette-blue, 14);
|
||||||
|
|
||||||
|
$palette-light-blue:
|
||||||
|
"225,245,254"
|
||||||
|
"179,229,252"
|
||||||
|
"129,212,250"
|
||||||
|
"79,195,247"
|
||||||
|
"41,182,246"
|
||||||
|
"3,169,244"
|
||||||
|
"3,155,229"
|
||||||
|
"2,136,209"
|
||||||
|
"2,119,189"
|
||||||
|
"1,87,155"
|
||||||
|
"128,216,255"
|
||||||
|
"64,196,255"
|
||||||
|
"0,176,255"
|
||||||
|
"0,145,234";
|
||||||
|
|
||||||
|
$palette-blue-grey:
|
||||||
|
"236,239,241"
|
||||||
|
"207,216,220"
|
||||||
|
"176,190,197"
|
||||||
|
"144,164,174"
|
||||||
|
"120,144,156"
|
||||||
|
"96,125,139"
|
||||||
|
"84,110,122"
|
||||||
|
"69,90,100"
|
||||||
|
"55,71,79"
|
||||||
|
"38,50,56";
|
||||||
|
|
||||||
|
$palette-blue-grey-50: nth($palette-blue-grey, 1);
|
||||||
|
$palette-blue-grey-100: nth($palette-blue-grey, 2);
|
||||||
|
$palette-blue-grey-200: nth($palette-blue-grey, 3);
|
||||||
|
$palette-blue-grey-300: nth($palette-blue-grey, 4);
|
||||||
|
$palette-blue-grey-400: nth($palette-blue-grey, 5);
|
||||||
|
$palette-blue-grey-500: nth($palette-blue-grey, 6);
|
||||||
|
$palette-blue-grey-600: nth($palette-blue-grey, 7);
|
||||||
|
$palette-blue-grey-700: nth($palette-blue-grey, 8);
|
||||||
|
$palette-blue-grey-800: nth($palette-blue-grey, 9);
|
||||||
|
$palette-blue-grey-900: nth($palette-blue-grey, 10);
|
||||||
|
|
||||||
|
$color-black: "0,0,0";
|
||||||
|
$color-white: "255,255,255";
|
||||||
|
|
||||||
|
//-- The two possible colors for overlayed text.
|
||||||
|
$styleguide-generate-template: false !default;
|
||||||
|
$color-dark-contrast: $color-white !default;
|
||||||
|
$color-light-contrast: $color-black !default;
|
|
@ -0,0 +1,200 @@
|
||||||
|
@import url('http://fonts.googleapis.com/css?family=Roboto:300,400,500,700');
|
||||||
|
@import "normalize.css";
|
||||||
|
@import "./mixins";
|
||||||
|
|
||||||
|
//-- App
|
||||||
|
html {
|
||||||
|
font-size: 62.5%;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
font-family: Roboto, sans-serif;
|
||||||
|
font-size: 1.6rem;
|
||||||
|
user-select: none;
|
||||||
|
-webkit-touch-callout: none;
|
||||||
|
* {
|
||||||
|
-webkit-tap-highlight-color: rgba(255, 255, 255, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
a, abbr, address, article, aside, audio, b, blockquote, body, caption, cite,
|
||||||
|
code, dd, del, dfn, dialog, div, dl, dt, em, fieldset, figure, footer, form, h1,
|
||||||
|
h2, h3, h4, h5, h6, header, hgroup, hr, html, i, iframe, img, ins, kbd, label,
|
||||||
|
legend, li, mark, menu, nav, object, ol, p, pre, q, samp, section, small, span,
|
||||||
|
strong, sub, sup, table, tbody, td, tfoot, th, thead, time, tr, ul, var, video {
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
border: 0;
|
||||||
|
outline: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
*, *:before, *:after {
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1, h2, h3, h4, h5, h6, label, p, button, abbr, a, span, small {
|
||||||
|
font-smoothing: antialiased;
|
||||||
|
text-size-adjust: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
text-decoration: none;
|
||||||
|
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar {
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
input:not([type="checkbox"]):not([type="radio"]), button {
|
||||||
|
outline: none;
|
||||||
|
appearance: none;
|
||||||
|
-webkit-touch-callout: none;
|
||||||
|
-webkit-tap-highlight-color: rgba(255, 255, 255, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//-- App wrapper to allow overlays to block scroll
|
||||||
|
[data-react-toolbox-app] {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100vw;
|
||||||
|
height: 100vh;
|
||||||
|
overflow-y: scroll;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- Material design font sizes
|
||||||
|
h1 small, h2 small, h3 small, h4 small, h5 small, h6 small {
|
||||||
|
@include typo-display-3($color-contrast: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
@include typo-display-3;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
@include typo-display-2;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
@include typo-display-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4 {
|
||||||
|
@include typo-headline;
|
||||||
|
}
|
||||||
|
|
||||||
|
h5 {
|
||||||
|
@include typo-title;
|
||||||
|
}
|
||||||
|
|
||||||
|
h6 {
|
||||||
|
@include typo-subhead;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
@include typo-body-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-- Flex
|
||||||
|
[data-flex] {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
body[data-flex] {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- Direction
|
||||||
|
[data-flex^="horizontal"] {
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-flex^="vertical"] {
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// -- Size {
|
||||||
|
[data-flex*="grow"] {
|
||||||
|
> *:not([data-column]):not([data-flex-grow]) {
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-flex-grow="min"] {
|
||||||
|
flex-grow: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-flex-grow="max"] {
|
||||||
|
flex-grow: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- Container properties
|
||||||
|
[data-flex*="wrap"] {
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-flex*="center"] {
|
||||||
|
justify-content: center;
|
||||||
|
align-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-flex-justify="start"] {
|
||||||
|
justify-content: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-flex-justify="center"] {
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-flex-justify="end"] {
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-flex-content="start"] {
|
||||||
|
align-content: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-flex-content="center"] {
|
||||||
|
align-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-flex-content="end"] {
|
||||||
|
align-content: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-flex-items="center"] {
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-flex-items="start"] {
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-flex-items="end"] {
|
||||||
|
align-items: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- Children properties
|
||||||
|
[data-flex-order="first"] {
|
||||||
|
order: -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-flex-order="last"] {
|
||||||
|
order: 999999;
|
||||||
|
}
|
|
@ -1,119 +0,0 @@
|
||||||
@import url('http://fonts.googleapis.com/css?family=Roboto:300,400,500,700')
|
|
||||||
@import './vendor.styl'
|
|
||||||
@import './normalize.styl'
|
|
||||||
|
|
||||||
// -- App ----------------------------------------------------------------------
|
|
||||||
body
|
|
||||||
position: absolute
|
|
||||||
height: 100%
|
|
||||||
width: 100%
|
|
||||||
margin: 0
|
|
||||||
padding: 0
|
|
||||||
font-family Roboto, sans-serif
|
|
||||||
-webkit-touch-callout: none
|
|
||||||
-webkit-user-select: none
|
|
||||||
-moz-user-select: moz-none
|
|
||||||
user-select: none
|
|
||||||
*
|
|
||||||
-webkit-tap-highlight-color: rgba(255, 255, 255, 0)
|
|
||||||
|
|
||||||
[data-toolbox]
|
|
||||||
position: absolute
|
|
||||||
left: 0
|
|
||||||
top: 0
|
|
||||||
width: 100vw
|
|
||||||
height: 100vh
|
|
||||||
overflow-y: scroll
|
|
||||||
|
|
||||||
a,abbr,address,article,aside,audio,b,blockquote,body,caption,cite,code,dd,del,dfn,dialog,div,dl,dt,em,fieldset,figure,footer,form,h1,h2,h3,h4,h5,h6,header,hgroup,hr,html,i,iframe,img,ins,kbd,label,legend,li,mark,menu,nav,object,ol,p,pre,q,samp,section,small,span,strong,sub,sup,table,tbody,td,tfoot,th,thead,time,tr,ul,var,video
|
|
||||||
border: 0
|
|
||||||
margin: 0
|
|
||||||
outline: 0
|
|
||||||
padding: 0
|
|
||||||
|
|
||||||
*, *:before, *:after
|
|
||||||
margin: 0
|
|
||||||
padding: 0
|
|
||||||
box-sizing: border-box
|
|
||||||
|
|
||||||
h1, h2, h3, h4, h5, h6, label, p, button, abbr, a, span, small
|
|
||||||
-webkit-font-smoothing: RENDER = antialiased
|
|
||||||
font-smoothing: RENDER
|
|
||||||
-webkit-text-size-adjust: 100%
|
|
||||||
-ms-text-size-adjust: 100%
|
|
||||||
text-size-adjust: 100%
|
|
||||||
|
|
||||||
a
|
|
||||||
text-decoration: none
|
|
||||||
-webkit-tap-highlight-color: rgba(0,0,0,0)
|
|
||||||
|
|
||||||
::-webkit-scrollbar
|
|
||||||
width: 0px
|
|
||||||
height: 0px
|
|
||||||
|
|
||||||
input:not([type="checkbox"]):not([type="radio"]), button
|
|
||||||
-webkit-appearance: none
|
|
||||||
-moz-appearance: none
|
|
||||||
appearance: none
|
|
||||||
-webkit-touch-callout: none
|
|
||||||
-webkit-tap-highlight-color: rgba(255, 255, 255, 0)
|
|
||||||
outline: none
|
|
||||||
|
|
||||||
// -- Data-Flex ----------------------------------------------------------------
|
|
||||||
[data-flex]
|
|
||||||
display-flex()
|
|
||||||
body&
|
|
||||||
position : absolute
|
|
||||||
left : 0
|
|
||||||
top : 0
|
|
||||||
bottom : 0
|
|
||||||
width : 100%
|
|
||||||
overflow : hidden
|
|
||||||
|
|
||||||
// -- Direction
|
|
||||||
[data-flex^="horizontal"]
|
|
||||||
flex-direction row
|
|
||||||
[data-flex^="vertical"]
|
|
||||||
flex-direction column
|
|
||||||
|
|
||||||
// -- Size
|
|
||||||
[data-flex*="grow"]
|
|
||||||
> *:not([data-column]):not([data-flex-grow])
|
|
||||||
flex-grow 1
|
|
||||||
[data-flex-grow="min"]
|
|
||||||
flex-grow 0
|
|
||||||
[data-flex-grow="max"]
|
|
||||||
flex-grow 2
|
|
||||||
|
|
||||||
// -- Container properties
|
|
||||||
[data-flex*="wrap"]
|
|
||||||
flex-wrap wrap
|
|
||||||
[data-flex*="center"]
|
|
||||||
justify-content center
|
|
||||||
align-content center
|
|
||||||
align-items center
|
|
||||||
[data-flex-justify="start"]
|
|
||||||
justify-content flex-start
|
|
||||||
[data-flex-justify="center"]
|
|
||||||
justify-content center
|
|
||||||
[data-flex-justify="end"]
|
|
||||||
justify-content flex-end
|
|
||||||
[data-flex-content="start"]
|
|
||||||
align-content flex-start
|
|
||||||
[data-flex-content="center"]
|
|
||||||
align-content center
|
|
||||||
[data-flex-content="end"]
|
|
||||||
align-content flex-end
|
|
||||||
[data-flex-items="center"]
|
|
||||||
align-items center
|
|
||||||
[data-flex-items="start"]
|
|
||||||
align-items flex-start
|
|
||||||
[data-flex-items="end"]
|
|
||||||
align-items flex-end
|
|
||||||
|
|
||||||
// -- Children properties
|
|
||||||
[data-flex-order="first"]
|
|
||||||
order: -1
|
|
||||||
|
|
||||||
[data-flex-order="last"]
|
|
||||||
order: 999999
|
|
|
@ -1,60 +0,0 @@
|
||||||
@import './vendor.styl'
|
|
||||||
|
|
||||||
// -- Colors
|
|
||||||
PRIMARY = #E91E63
|
|
||||||
PRIMARY_DARK = darken(PRIMARY, 25%)
|
|
||||||
PRIMARY_LIGHT = lighten(PRIMARY, 25%)
|
|
||||||
ACCENT = #03A9F4
|
|
||||||
|
|
||||||
TEXT = #212121
|
|
||||||
TEXT_ACCENT = #727272
|
|
||||||
|
|
||||||
DIVIDER = lighten(#B6B6B6, 75%)
|
|
||||||
BACKGROUND = #ffffff
|
|
||||||
WHITE = #ffffff
|
|
||||||
SUCCESS = #4CAF50
|
|
||||||
CANCEL = #F44336
|
|
||||||
WARNING = #FFC107
|
|
||||||
|
|
||||||
// -- Fonts
|
|
||||||
FONT_FAMILY = "Roboto", "Helvetica Neue", "Helvetica", "sans-serif"
|
|
||||||
FONT_SIZE = 16px
|
|
||||||
FONT_SIZE_TINY = 80%
|
|
||||||
FONT_SIZE_SMALL = 90%
|
|
||||||
FONT_SIZE_NORMAL = 100%
|
|
||||||
FONT_SIZE_BIG = 120%
|
|
||||||
FONT_WEIGHT_THIN = 300
|
|
||||||
FONT_WEIGHT_NORMAL = 400
|
|
||||||
FONT_WEIGHT_BOLD = 700
|
|
||||||
|
|
||||||
// -- Sizes
|
|
||||||
UNIT = 4rem
|
|
||||||
SPACE = (UNIT * 0.29)
|
|
||||||
OFFSET = (SPACE * 1.75)
|
|
||||||
MENU_WIDTH = (3.85 * UNIT)
|
|
||||||
HEADER_HEIGHT = (1.65 * UNIT)
|
|
||||||
INPUT_HEIGHT = (2 * SPACE)
|
|
||||||
BUTTON_HEIGHT = (2.5 * SPACE)
|
|
||||||
BUTTON_CIRCLE_HEIGHT = (2.75 * SPACE)
|
|
||||||
BUTTON_CIRCLE_MINI_HEIGHT = (2 * SPACE)
|
|
||||||
LOADING_HEIGHT = (1.5 * UNIT)
|
|
||||||
PROGRESS_BAR_HEIGHT = (SPACE / 4)
|
|
||||||
|
|
||||||
// -- Shadows
|
|
||||||
ZDEPTH_SHADOW_1 = 0 1px 6px rgba(0,0,0,0.12), 0 1px 4px rgba(0,0,0,0.24)
|
|
||||||
ZDEPTH_SHADOW_2 = 0 3px 10px rgba(0,0,0,0.16), 0 3px 10px rgba(0,0,0,0.23)
|
|
||||||
ZDEPTH_SHADOW_3 = 0 10px 30px rgba(0,0,0,0.19), 0 6px 10px rgba(0,0,0,0.23)
|
|
||||||
ZDEPTH_SHADOW_4 = 0 14px 45px rgba(0,0,0,0.25), 0 10px 18px rgba(0,0,0,0.22)
|
|
||||||
ZDEPTH_SHADOW_5 = 0 19px 60px rgba(0,0,0,0.30), 0 15px 20px rgba(0,0,0,0.22)
|
|
||||||
|
|
||||||
// -- Animations
|
|
||||||
ANIMATION_DURATION = 450ms
|
|
||||||
ANIMATION_EASE = cubic-bezier(.55,0,.1,1)
|
|
||||||
ANIMATION_DELAY = (ANIMATION_DURATION / 5)
|
|
||||||
|
|
||||||
// -- Z Indexes
|
|
||||||
Z_INDEX_HIGHER = 200
|
|
||||||
Z_INDEX_HIGH = 100
|
|
||||||
Z_INDEX_NORMAL = 1
|
|
||||||
Z_INDEX_LOW = -100
|
|
||||||
Z_INDEX_LOWER = -200
|
|
|
@ -1,13 +1,12 @@
|
||||||
/* global React */
|
import React from 'react';
|
||||||
|
import PureRenderMixin from 'react-addons-pure-render-mixin';
|
||||||
import { addons } from 'react/addons';
|
import style from './style';
|
||||||
import css from './style';
|
|
||||||
import time from '../utils/time';
|
import time from '../utils/time';
|
||||||
import Calendar from '../calendar';
|
import Calendar from '../calendar';
|
||||||
import Dialog from '../dialog';
|
import Dialog from '../dialog';
|
||||||
|
|
||||||
export default React.createClass({
|
export default React.createClass({
|
||||||
mixins: [addons.PureRenderMixin],
|
mixins: [PureRenderMixin],
|
||||||
|
|
||||||
displayName: 'CalendarDialog',
|
displayName: 'CalendarDialog',
|
||||||
|
|
||||||
|
@ -27,8 +26,8 @@ export default React.createClass({
|
||||||
date: this.props.initialDate,
|
date: this.props.initialDate,
|
||||||
display: 'months',
|
display: 'months',
|
||||||
actions: [
|
actions: [
|
||||||
{ label: 'Cancel', type: 'flat accent', onClick: this.onDateCancel },
|
{ label: 'Cancel', className: style.button, onClick: this.onDateCancel },
|
||||||
{ label: 'Ok', type: 'flat accent', onClick: this.onDateSelected }
|
{ label: 'Ok', className: style.button, onClick: this.onDateSelected }
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
@ -59,28 +58,30 @@ export default React.createClass({
|
||||||
},
|
},
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const className = `display-${this.state.display}`;
|
const display = `display-${this.state.display}`;
|
||||||
|
const headerClassName = `${style.header} ${style[display]}`;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog ref="dialog" className={className} type={css.dialog} actions={this.state.actions}>
|
<Dialog ref="dialog" type="custom" className={style.dialog} actions={this.state.actions}>
|
||||||
<header className={css.header}>
|
<header className={headerClassName}>
|
||||||
<span className={css.headerWeekday}>
|
<span className={style.weekday}>
|
||||||
{time.getFullDayOfWeek(this.state.date.getDay())}
|
{time.getFullDayOfWeek(this.state.date.getDay())}
|
||||||
</span>
|
</span>
|
||||||
<div onClick={this.displayMonths}>
|
<div onClick={this.displayMonths}>
|
||||||
<span className={css.headerMonth}>{time.getShortMonth(this.state.date)}</span>
|
<span className={style.month}>{time.getShortMonth(this.state.date)}</span>
|
||||||
<span className={css.headerDay}>{this.state.date.getDate()}</span>
|
<span className={style.day}>{this.state.date.getDate()}</span>
|
||||||
</div>
|
</div>
|
||||||
<span className={css.headerYear} onClick={this.displayYears}>
|
<span className={style.year} onClick={this.displayYears}>
|
||||||
{this.state.date.getFullYear()}
|
{this.state.date.getFullYear()}
|
||||||
</span>
|
</span>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<div className={css.calendarWrapper}>
|
<div className={style.wrapper}>
|
||||||
<Calendar
|
<Calendar
|
||||||
ref="calendar"
|
ref="calendar"
|
||||||
display={this.state.display}
|
display={this.state.display}
|
||||||
onChange={this.onCalendarChange}
|
onChange={this.onCalendarChange}
|
||||||
selectedDate={this.props.date} />
|
selectedDate={this.state.date} />
|
||||||
</div>
|
</div>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
/* global React */
|
import React from 'react';
|
||||||
|
import PureRenderMixin from 'react-addons-pure-render-mixin';
|
||||||
import { addons } from 'react/addons';
|
import style from './style';
|
||||||
import time from '../utils/time';
|
import time from '../utils/time';
|
||||||
|
import events from '../utils/events';
|
||||||
import CalendarDialog from './dialog';
|
import CalendarDialog from './dialog';
|
||||||
import Input from '../input';
|
import Input from '../input';
|
||||||
|
|
||||||
export default React.createClass({
|
export default React.createClass({
|
||||||
mixins: [addons.PureRenderMixin],
|
mixins: [PureRenderMixin],
|
||||||
|
|
||||||
displayName: 'DatePicker',
|
displayName: 'DatePicker',
|
||||||
|
|
||||||
|
@ -27,7 +28,8 @@ export default React.createClass({
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
openCalendarDialog () {
|
openCalendarDialog (event) {
|
||||||
|
events.pauseEvent(event);
|
||||||
this.refs.dialog.show();
|
this.refs.dialog.show();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -46,18 +48,21 @@ export default React.createClass({
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div data-toolbox='date-picker'>
|
||||||
<Input
|
<Input
|
||||||
ref="input"
|
ref='input'
|
||||||
type="text"
|
type='text'
|
||||||
disabled={true}
|
readOnly={true}
|
||||||
onClick={this.openCalendarDialog}
|
className={style.input}
|
||||||
placeholder="Pick up date"
|
onMouseDown={this.openCalendarDialog}
|
||||||
value={this.state.value ? this.formatDate(this.state.value) : null} />
|
placeholder='Pick up date'
|
||||||
|
value={this.state.value ? this.formatDate(this.state.value) : null}
|
||||||
|
/>
|
||||||
<CalendarDialog
|
<CalendarDialog
|
||||||
ref="dialog"
|
ref='dialog'
|
||||||
initialDate={this.state.value}
|
initialDate={this.state.value}
|
||||||
onDateSelected={this.onDateSelected} />
|
onDateSelected={this.onDateSelected}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,88 @@
|
||||||
|
@import "../variables";
|
||||||
|
|
||||||
|
$datepicker-primary: $color-primary;
|
||||||
|
$datepicker-primary-contrast: $color-primary-contrast;
|
||||||
|
$datepicker-primary-dark: $color-primary-dark;
|
||||||
|
$datepicker-primary-color: unquote("rgb(#{$datepicker-primary})") !default;
|
||||||
|
$datepicker-primary-hover-color: unquote("rgba(#{$datepicker-primary}, 0.20)") !default;
|
||||||
|
$datepicker-primary-contrast-color: unquote("rgb(#{$datepicker-primary-contrast})") !default;
|
||||||
|
$datepicker-primary-dark-color: unquote("rgb(#{$datepicker-primary-dark})") !default;
|
||||||
|
$datepicker-dialog-width: 30 * $unit;
|
||||||
|
$datepicker-inactive-opacity: .6;
|
||||||
|
|
||||||
|
.input > [role="input"] {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
padding-bottom: $unit;
|
||||||
|
color: $datepicker-primary-contrast-color;
|
||||||
|
text-align: center;
|
||||||
|
background-color: $datepicker-primary-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
.weekday {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
font-size: 1.4 * $unit;
|
||||||
|
line-height: 2 * $unit;
|
||||||
|
background-color: $datepicker-primary-dark-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
.month {
|
||||||
|
display: block;
|
||||||
|
padding: $unit;
|
||||||
|
font-size: 1.8 * $unit;
|
||||||
|
text-transform: uppercase;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.day {
|
||||||
|
display: block;
|
||||||
|
font-size: 5 * $unit;
|
||||||
|
line-height: 4 * $unit;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.year {
|
||||||
|
display: inline-block;
|
||||||
|
margin-top: $unit;
|
||||||
|
font-size: 1.8 * $unit;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wrapper {
|
||||||
|
padding: $unit .5 * $unit 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.display-years {
|
||||||
|
.day, .month {
|
||||||
|
opacity: $datepicker-inactive-opacity;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.display-months {
|
||||||
|
.year {
|
||||||
|
opacity: $datepicker-inactive-opacity;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog > [role="content"] {
|
||||||
|
width: $datepicker-dialog-width;
|
||||||
|
|
||||||
|
> [role="body"] {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
> [role="navigation"] > .button {
|
||||||
|
color: $datepicker-primary-color;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: $datepicker-primary-hover-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus:not(:active) {
|
||||||
|
background: $datepicker-primary-hover-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,53 +0,0 @@
|
||||||
@import '../constants'
|
|
||||||
|
|
||||||
TOTAL_WIDTH = 330px
|
|
||||||
|
|
||||||
:local(.dialog)
|
|
||||||
padding : 0
|
|
||||||
text-align : center
|
|
||||||
width : TOTAL_WIDTH
|
|
||||||
|
|
||||||
> nav
|
|
||||||
margin-top : 0
|
|
||||||
padding-bottom : 10px
|
|
||||||
|
|
||||||
:local(.header)
|
|
||||||
background-color : ACCENT
|
|
||||||
color : white
|
|
||||||
|
|
||||||
:local(.headerWeekday)
|
|
||||||
background-color : darken(ACCENT, 20%)
|
|
||||||
display : block
|
|
||||||
font-size : 14px
|
|
||||||
line-height : 1.8
|
|
||||||
width : 100%
|
|
||||||
|
|
||||||
:local(.headerMonth)
|
|
||||||
cursor : pointer
|
|
||||||
display : block
|
|
||||||
font-size : 18px
|
|
||||||
padding : 10px
|
|
||||||
text-transform : uppercase
|
|
||||||
|
|
||||||
:local(.headerDay)
|
|
||||||
cursor : pointer
|
|
||||||
display : block
|
|
||||||
font-size : 50px
|
|
||||||
line-height : 40px
|
|
||||||
|
|
||||||
:local(.headerYear)
|
|
||||||
cursor : pointer
|
|
||||||
display : block
|
|
||||||
font-size : 18px
|
|
||||||
padding : 10px
|
|
||||||
|
|
||||||
:local(.calendarWrapper)
|
|
||||||
padding : 10px 5px
|
|
||||||
|
|
||||||
:local(.dialog)
|
|
||||||
&.display-years
|
|
||||||
:local(.headerDay), :local(.headerMonth)
|
|
||||||
opacity : .7
|
|
||||||
|
|
||||||
&.display-months :local(.headerYear)
|
|
||||||
opacity : .7
|
|
|
@ -1,9 +1,11 @@
|
||||||
/* global React */
|
import React from 'react';
|
||||||
|
import PureRenderMixin from 'react-addons-pure-render-mixin';
|
||||||
|
import Button from '../button';
|
||||||
import style from './style';
|
import style from './style';
|
||||||
import Navigation from '../navigation';
|
|
||||||
|
|
||||||
export default React.createClass({
|
export default React.createClass({
|
||||||
|
mixins: [PureRenderMixin],
|
||||||
|
|
||||||
displayName: 'Dialog',
|
displayName: 'Dialog',
|
||||||
|
|
||||||
propTypes: {
|
propTypes: {
|
||||||
|
@ -17,7 +19,7 @@ export default React.createClass({
|
||||||
getDefaultProps () {
|
getDefaultProps () {
|
||||||
return {
|
return {
|
||||||
actions: [],
|
actions: [],
|
||||||
className: 'normal'
|
type: 'normal'
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -25,18 +27,30 @@ export default React.createClass({
|
||||||
return { active: this.props.active };
|
return { active: this.props.active };
|
||||||
},
|
},
|
||||||
|
|
||||||
|
renderActions () {
|
||||||
|
return this.props.actions.map((action, idx) => {
|
||||||
|
let className = style.button;
|
||||||
|
if (action.className) className += ` ${action.className}`;
|
||||||
|
return <Button key={idx} {...action} className={className} />;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
let rootClass = style.root;
|
let className = `${style.root} ${style[this.props.type]}`;
|
||||||
let containerClass = `${style.container} ${this.props.className}`;
|
if (this.state.active) className += ` ${style.active}`;
|
||||||
if (this.state.active) rootClass += ' active';
|
if (this.props.className) className += ` ${this.props.className}`;
|
||||||
if (this.props.type) containerClass += ` ${this.props.type}`;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div data-react-toolbox='dialog' data-flex='vertical center' className={rootClass}>
|
<div data-react-toolbox='dialog' className={className}>
|
||||||
<div className={containerClass}>
|
<div role='overlay' className={style.overlay} />
|
||||||
{ this.props.title ? <h1>{this.props.title}</h1> : null }
|
<div role='content' className={style.content}>
|
||||||
{ this.props.children }
|
<section role='body' className={style.body}>
|
||||||
{ this.props.actions.length > 0 ? <Navigation actions={this.props.actions}/> : null }
|
{ this.props.title ? <h6 className={style.title}>{this.props.title}</h6> : null }
|
||||||
|
{ this.props.children }
|
||||||
|
</section>
|
||||||
|
<nav role='navigation' className={style.navigation}>
|
||||||
|
{ this.renderActions() }
|
||||||
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -0,0 +1,107 @@
|
||||||
|
@import "../variables";
|
||||||
|
@import "../mixins";
|
||||||
|
|
||||||
|
$dialog-color-title: unquote("rgb(#{$color-black})") !default;
|
||||||
|
$dialog-color-white: unquote("rgb(#{$color-white})") !default;
|
||||||
|
$dialog-content-padding: 2.4 * $unit;
|
||||||
|
$dialog-navigation-padding: .8 * $unit;
|
||||||
|
$dialog-translate-y: 4 * $unit;
|
||||||
|
|
||||||
|
.root {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
z-index: $z-index-high;
|
||||||
|
display: flex;
|
||||||
|
width: 100vw;
|
||||||
|
height: 100vh;
|
||||||
|
flex-direction: column;
|
||||||
|
pointer-events: none;
|
||||||
|
justify-content: center;
|
||||||
|
align-content: center;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
> .content {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(-$dialog-translate-y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.overlay {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-color: $color-overlay;
|
||||||
|
opacity: 0;
|
||||||
|
transition-timing-function: $animation-curve-default;
|
||||||
|
transition-duration: $animation-duration;
|
||||||
|
transition-property: opacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
display: flex;
|
||||||
|
max-width: 96vw;
|
||||||
|
max-height: 96vh;
|
||||||
|
flex-direction: column;
|
||||||
|
background-color: $dialog-color-white;
|
||||||
|
border-radius: $border-radius;
|
||||||
|
box-shadow: $zdepth-shadow-5;
|
||||||
|
transition-delay: $animation-delay;
|
||||||
|
transition-timing-function: $animation-curve-default;
|
||||||
|
transition-duration: $animation-duration;
|
||||||
|
transition-property: opacity, transform;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
@include typo-title();
|
||||||
|
margin-bottom: 1.6 * $unit;
|
||||||
|
color: $dialog-color-title;
|
||||||
|
flex-grow: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.body {
|
||||||
|
padding: $dialog-content-padding;
|
||||||
|
overflow-y: scroll;
|
||||||
|
color: $color-text-secondary;
|
||||||
|
flex-grow: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navigation {
|
||||||
|
padding: $dialog-navigation-padding;
|
||||||
|
text-align: right;
|
||||||
|
flex-grow: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button {
|
||||||
|
min-width: 0;
|
||||||
|
padding-right: $dialog-navigation-padding;
|
||||||
|
padding-left: $dialog-navigation-padding;
|
||||||
|
margin-left: $dialog-navigation-padding;
|
||||||
|
}
|
||||||
|
|
||||||
|
.active {
|
||||||
|
pointer-events: all;
|
||||||
|
|
||||||
|
> .overlay {
|
||||||
|
opacity: $color-overlay-opacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
> .content {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.small > .content {
|
||||||
|
width: 30vw;
|
||||||
|
}
|
||||||
|
|
||||||
|
.normal > .content {
|
||||||
|
width: 50vw;
|
||||||
|
}
|
||||||
|
|
||||||
|
.large > .content {
|
||||||
|
width: 96vw;
|
||||||
|
}
|
|
@ -1,52 +0,0 @@
|
||||||
@import '../constants'
|
|
||||||
|
|
||||||
:local(.container)
|
|
||||||
margin : SPACE
|
|
||||||
padding : SPACE (SPACE * 1.5)
|
|
||||||
background-color : WHITE
|
|
||||||
border-radius : (SPACE / 5)
|
|
||||||
box-shadow : ZDEPTH_SHADOW_5
|
|
||||||
transition-property : opacity, transform
|
|
||||||
transition-duration : ANIMATION_DURATION
|
|
||||||
transition-timing-function : ANIMATION_EASE
|
|
||||||
transition-delay : ANIMATION_DELAY
|
|
||||||
> h1
|
|
||||||
margin-bottom : SPACE
|
|
||||||
> nav
|
|
||||||
margin-top : SPACE
|
|
||||||
text-align : right
|
|
||||||
> .raised
|
|
||||||
margin-left : SPACE
|
|
||||||
|
|
||||||
:local(.root)
|
|
||||||
z-index : 3
|
|
||||||
position : fixed
|
|
||||||
left : 0
|
|
||||||
top : 0
|
|
||||||
width : 100vw
|
|
||||||
height : 100vh
|
|
||||||
background-color : rgba(0,0,0,0.5)
|
|
||||||
transition-property : opacity
|
|
||||||
transition-duration : (ANIMATION_DURATION / 2)
|
|
||||||
transition-timing-function : ANIMATION_EASE
|
|
||||||
|
|
||||||
&:not(.active)
|
|
||||||
pointer-events : none
|
|
||||||
opacity : 0
|
|
||||||
transition-delay : (ANIMATION_DELAY * 2)
|
|
||||||
> :local(.container)
|
|
||||||
opacity : 0
|
|
||||||
transform : translateY(-(UNIT))
|
|
||||||
&.active
|
|
||||||
opacity : 1
|
|
||||||
> :local(.container)
|
|
||||||
opacity : 1
|
|
||||||
transform : translateY(0%)
|
|
||||||
|
|
||||||
// -- Overrides
|
|
||||||
:local(.container).small
|
|
||||||
width : 33vw
|
|
||||||
:local(.container).normal
|
|
||||||
width : 50vw
|
|
||||||
:local(.container).large
|
|
||||||
width : 96vw
|
|
|
@ -1,10 +1,9 @@
|
||||||
/* global React */
|
import React from 'react';
|
||||||
|
import PureRenderMixin from 'react-addons-pure-render-mixin';
|
||||||
import { addons } from 'react/addons';
|
import style from './style.scss';
|
||||||
import css from './style';
|
|
||||||
|
|
||||||
export default React.createClass({
|
export default React.createClass({
|
||||||
mixins: [addons.PureRenderMixin],
|
mixins: [PureRenderMixin],
|
||||||
|
|
||||||
displayName: 'Drawer',
|
displayName: 'Drawer',
|
||||||
|
|
||||||
|
@ -33,15 +32,14 @@ export default React.createClass({
|
||||||
},
|
},
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
let className = `${css.root} ${this.props.className}`;
|
let className = `${style.drawer} ${style[this.props.type]}`;
|
||||||
if (this.props.type) className += ` ${this.props.type}`;
|
if (this.state.active) className += ` ${style.active}`;
|
||||||
if (this.props.hideable) className += ' hideable';
|
if (this.props.className) className += ` ${this.props.className}`;
|
||||||
if (this.state.active) className += ' active';
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={className}>
|
<div data-react-toolbox='drawer' className={className}>
|
||||||
<div className={css.overlay} onClick={this.handleOverlayClick}></div>
|
<div className={style.overlay} onClick={this.handleOverlayClick}></div>
|
||||||
<aside className={css.container}>
|
<aside className={style.content}>
|
||||||
{ this.props.children }
|
{ this.props.children }
|
||||||
</aside>
|
</aside>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -0,0 +1,81 @@
|
||||||
|
@import "../variables";
|
||||||
|
@import "../mixins";
|
||||||
|
|
||||||
|
$drawer-width: 24 * $unit;
|
||||||
|
$drawer-bg-color: unquote("rgb(#{$palette-grey-50})") !default;
|
||||||
|
$drawer-text-color: unquote("rgb(#{$palette-grey-800})") !default;
|
||||||
|
$drawer-border-color: unquote("rgb(#{$palette-grey-300})") !default;
|
||||||
|
|
||||||
|
.drawer {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
left: 0;
|
||||||
|
z-index: 2;
|
||||||
|
width: 100vw;
|
||||||
|
height: 100vh;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.active {
|
||||||
|
pointer-events: all;
|
||||||
|
|
||||||
|
> .content {
|
||||||
|
transition-delay: $animation-delay;
|
||||||
|
transform: translateX(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
> .overlay {
|
||||||
|
opacity: $color-overlay-opacity;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.left {
|
||||||
|
> .content {
|
||||||
|
left: 0;
|
||||||
|
border-right: 1px solid $drawer-border-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:not(.active) > .content {
|
||||||
|
transform: translateX(- $drawer-width);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.right {
|
||||||
|
> .content {
|
||||||
|
right: 0;
|
||||||
|
border-left: 1px solid $drawer-border-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:not(.active) > .content {
|
||||||
|
transform: translateX($drawer-width);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.overlay {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-color: $color-overlay;
|
||||||
|
opacity: 0;
|
||||||
|
transition-timing-function: $animation-curve-default;
|
||||||
|
transition-duration: $animation-duration;
|
||||||
|
transition-property: opacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
@include shadow-2dp();
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
display: block;
|
||||||
|
width: $drawer-width;
|
||||||
|
height: 100%;
|
||||||
|
overflow-y: scroll;
|
||||||
|
color: $drawer-text-color;
|
||||||
|
background-color: $drawer-bg-color;
|
||||||
|
transition-delay: 0s;
|
||||||
|
transition-timing-function: $animation-curve-default;
|
||||||
|
transition-duration: $animation-duration;
|
||||||
|
transition-property: transform;
|
||||||
|
transform-style: preserve-3d;
|
||||||
|
will-change: transform;
|
||||||
|
}
|
|
@ -1,60 +0,0 @@
|
||||||
@import '../constants'
|
|
||||||
|
|
||||||
WIDTH = (4 * UNIT)
|
|
||||||
|
|
||||||
:local(.root)
|
|
||||||
height : 100vh
|
|
||||||
pointer-events : none
|
|
||||||
position : fixed
|
|
||||||
top : 0
|
|
||||||
left : 0
|
|
||||||
right : 0
|
|
||||||
width : 100vw
|
|
||||||
z-index : 2
|
|
||||||
|
|
||||||
:local(.overlay)
|
|
||||||
background-color : black
|
|
||||||
height : 100%
|
|
||||||
opacity : 0
|
|
||||||
transition-duration : .5 * ANIMATION_DURATION
|
|
||||||
transition-property : opacity
|
|
||||||
transition-timing-function : ANIMATION_EASE
|
|
||||||
width : 100%
|
|
||||||
|
|
||||||
:local(.container)
|
|
||||||
background-color : WHITE
|
|
||||||
box-shadow : ZDEPTH_SHADOW_1
|
|
||||||
display : block
|
|
||||||
height : 100%
|
|
||||||
overflow-y : scroll
|
|
||||||
position : absolute
|
|
||||||
top : 0
|
|
||||||
transform-style : preserve-3d
|
|
||||||
transition-delay : 0s
|
|
||||||
transition-duration : .5 * ANIMATION_DURATION
|
|
||||||
transition-property : transform
|
|
||||||
transition-timing-function : ANIMATION_EASE
|
|
||||||
width : WIDTH
|
|
||||||
will-change : transform
|
|
||||||
|
|
||||||
:local(.root)
|
|
||||||
&.left
|
|
||||||
> :local(.container)
|
|
||||||
left : 0
|
|
||||||
&:not(.active) > :local(.container)
|
|
||||||
transform : translateX(- WIDTH)
|
|
||||||
|
|
||||||
&.right
|
|
||||||
> :local(.container)
|
|
||||||
right : 0
|
|
||||||
&:not(.active) > :local(.container)
|
|
||||||
transform : translateX(WIDTH)
|
|
||||||
|
|
||||||
&.active
|
|
||||||
pointer-events : all
|
|
||||||
> :local(.container)
|
|
||||||
transition-delay : ANIMATION_DELAY
|
|
||||||
transform : translateX(0)
|
|
||||||
|
|
||||||
> :local(.overlay)
|
|
||||||
opacity : .5
|
|
|
@ -1,11 +1,23 @@
|
||||||
/* global React */
|
import React from 'react';
|
||||||
|
import ReactDOM from 'react-dom';
|
||||||
import { addons } from 'react/addons';
|
import PureRenderMixin from 'react-addons-pure-render-mixin';
|
||||||
import style from './style';
|
|
||||||
import Ripple from '../ripple';
|
import Ripple from '../ripple';
|
||||||
|
import style from './style';
|
||||||
|
|
||||||
|
function _selectValue (value, dataSource) {
|
||||||
|
let item;
|
||||||
|
if (value) {
|
||||||
|
for (item of dataSource) {
|
||||||
|
if (item.value.toString() === value.toString()) break;
|
||||||
|
}
|
||||||
|
return item;
|
||||||
|
} else {
|
||||||
|
return dataSource[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export default React.createClass({
|
export default React.createClass({
|
||||||
mixins: [addons.PureRenderMixin],
|
mixins: [PureRenderMixin],
|
||||||
|
|
||||||
displayName: 'Dropdown',
|
displayName: 'Dropdown',
|
||||||
|
|
||||||
|
@ -16,7 +28,6 @@ export default React.createClass({
|
||||||
label: React.PropTypes.string,
|
label: React.PropTypes.string,
|
||||||
onChange: React.PropTypes.func,
|
onChange: React.PropTypes.func,
|
||||||
template: React.PropTypes.func,
|
template: React.PropTypes.func,
|
||||||
type: React.PropTypes.string,
|
|
||||||
value: React.PropTypes.string
|
value: React.PropTypes.string
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -24,20 +35,21 @@ export default React.createClass({
|
||||||
return {
|
return {
|
||||||
className: '',
|
className: '',
|
||||||
dataSource: [],
|
dataSource: [],
|
||||||
type: 'normal'
|
up: false
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
getInitialState () {
|
getInitialState () {
|
||||||
return {
|
return {
|
||||||
active: false,
|
active: false,
|
||||||
selected: _selectValue(this.props.value, this.props.dataSource)
|
selected: _selectValue(this.props.value, this.props.dataSource),
|
||||||
|
width: undefined
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
componentDidMount () {
|
componentDidMount () {
|
||||||
this.setState({
|
this.setState({
|
||||||
height: this.refs.values.getDOMNode().firstElementChild.getBoundingClientRect().height
|
width: ReactDOM.findDOMNode(this).getBoundingClientRect().width
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -47,13 +59,17 @@ export default React.createClass({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
onSelect () {
|
handleClick (event) {
|
||||||
if (!this.props.disabled) {
|
let client = event.target.getBoundingClientRect();
|
||||||
this.setState({active: true});
|
let screen_height = window.innerHeight || document.documentElement.offsetHeight;
|
||||||
}
|
|
||||||
|
this.setState({
|
||||||
|
active: true,
|
||||||
|
up: client.top > ((screen_height / 2) + client.height)
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
onItem (id) {
|
handleClickValue (id) {
|
||||||
if (!this.props.disabled) {
|
if (!this.props.disabled) {
|
||||||
let value = id.toString();
|
let value = id.toString();
|
||||||
for (let item of this.props.dataSource) {
|
for (let item of this.props.dataSource) {
|
||||||
|
@ -68,24 +84,17 @@ export default React.createClass({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
render () {
|
renderValues () {
|
||||||
let stylesheet;
|
let items = this.props.dataSource.map((item, index) => {
|
||||||
let className = `${style.root} ${this.props.className}`;
|
let className;
|
||||||
if (this.props.type) className += ` ${this.props.type}`;
|
if (item.value === this.state.selected.value) className = ` ${style.selected}`;
|
||||||
if (this.props.disabled) className += ' disabled';
|
|
||||||
if (this.state.active === true) {
|
|
||||||
className += ' active';
|
|
||||||
stylesheet = { height: this.state.height * this.props.dataSource.length };
|
|
||||||
}
|
|
||||||
|
|
||||||
const items = this.props.dataSource.map((item, index) => {
|
|
||||||
return (
|
return (
|
||||||
<li
|
<li
|
||||||
key={index}
|
key={index}
|
||||||
|
className={className}
|
||||||
id={item.value}
|
id={item.value}
|
||||||
onClick={this.onItem.bind(this, item.value)}
|
onClick={this.handleClickValue.bind(this, item.value)}
|
||||||
style={{position: 'relative'}}
|
|
||||||
className={ item.value === this.state.selected.value ? 'selected' : null}
|
|
||||||
>
|
>
|
||||||
{ this.props.template ? this.props.template(item) : item.label }
|
{ this.props.template ? this.props.template(item) : item.label }
|
||||||
<Ripple className={style.ripple}/>
|
<Ripple className={style.ripple}/>
|
||||||
|
@ -93,11 +102,24 @@ export default React.createClass({
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let className = style.values;
|
||||||
|
if (this.state.up) className += ` ${style.up}`;
|
||||||
|
let valuesStyle = {width: this.state.width};
|
||||||
|
|
||||||
|
return <ul ref='values' className={className} style={valuesStyle}>{ items }</ul>;
|
||||||
|
},
|
||||||
|
|
||||||
|
render () {
|
||||||
|
let className = style.root;
|
||||||
|
if (this.props.className) className += ` ${this.props.className}`;
|
||||||
|
if (this.props.disabled) className += ` ${style.disabled}`;
|
||||||
|
if (this.state.active) className += ` ${style.active}`;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div data-react-toolbox='dropdown' className={className}>
|
<div data-react-toolbox='dropdown' className={className}>
|
||||||
{this.props.label ? <label>{this.props.label}</label> : null}
|
{this.props.label ? <label className={style.label}>{this.props.label}</label> : null}
|
||||||
<ul ref='values' className={style.values} style={stylesheet}>{ items }</ul>
|
{ this.renderValues() }
|
||||||
<div ref='value' className={style.value} onClick={this.onSelect}>
|
<div ref='value' className={style.value} onClick={this.handleClick}>
|
||||||
{ this.props.template ? this.props.template(this.state.selected) : <span>{this.state.selected.label}</span> }
|
{ this.props.template ? this.props.template(this.state.selected) : <span>{this.state.selected.label}</span> }
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -112,15 +134,3 @@ export default React.createClass({
|
||||||
this.setState({selected: data});
|
this.setState({selected: data});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
function _selectValue (value, dataSource) {
|
|
||||||
let item;
|
|
||||||
if (value) {
|
|
||||||
for (item of dataSource) {
|
|
||||||
if (item.value.toString() === value.toString()) break;
|
|
||||||
}
|
|
||||||
return item;
|
|
||||||
} else {
|
|
||||||
return dataSource[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -0,0 +1,111 @@
|
||||||
|
@import "../variables";
|
||||||
|
@import "../mixins";
|
||||||
|
$dropdown-color-white: unquote("rgb(#{$color-white})");
|
||||||
|
$dropdown-color-primary: unquote("rgb(#{$color-primary})");
|
||||||
|
$dropdown-color-primary-contrast: unquote("rgb(#{$color-primary-contrast})");
|
||||||
|
$dropdown-value-hover-background: unquote("rgb(#{$palette-grey-200})");
|
||||||
|
|
||||||
|
.root {
|
||||||
|
position: relative;
|
||||||
|
width: inherit;
|
||||||
|
margin-bottom: $offset;
|
||||||
|
color: $color-text;
|
||||||
|
border-bottom: 1px solid $color-divider;
|
||||||
|
&:not(.active) {
|
||||||
|
> .values {
|
||||||
|
max-height: 0;
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&.active {
|
||||||
|
> .label, > .value {
|
||||||
|
opacity: .5;
|
||||||
|
}
|
||||||
|
> .values {
|
||||||
|
max-height: $items-overflow-max-height;
|
||||||
|
visibility: visible;
|
||||||
|
box-shadow: $zdepth-shadow-1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&.disabled {
|
||||||
|
color: $color-text-secondary;
|
||||||
|
pointer-events: none;
|
||||||
|
border-bottom-style: dotted;
|
||||||
|
> .value:after {
|
||||||
|
transform: scale(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.label, .value {
|
||||||
|
transition: opacity $animation-duration $animation-curve-default;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label {
|
||||||
|
font-size: $font-size-tiny;
|
||||||
|
color: $color-text-secondary;
|
||||||
|
}
|
||||||
|
|
||||||
|
.values {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 2;
|
||||||
|
overflow-x: hidden;
|
||||||
|
overflow-y: scroll;
|
||||||
|
list-style: none;
|
||||||
|
background-color: $dropdown-color-white;
|
||||||
|
border-radius: $border-radius;
|
||||||
|
transition-timing-function: $animation-curve-default;
|
||||||
|
transition-duration: $animation-duration;
|
||||||
|
transition-property: max-height, box-shadow;
|
||||||
|
> * {
|
||||||
|
position: relative;
|
||||||
|
padding: $unit;
|
||||||
|
overflow: hidden;
|
||||||
|
cursor: pointer;
|
||||||
|
&:hover {
|
||||||
|
background-color: $dropdown-value-hover-background;
|
||||||
|
}
|
||||||
|
&.selected {
|
||||||
|
color: $dropdown-color-primary;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&:not(.up) {
|
||||||
|
top: 0;
|
||||||
|
bottom: auto;
|
||||||
|
}
|
||||||
|
&.up {
|
||||||
|
top: auto;
|
||||||
|
bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.value {
|
||||||
|
display: block;
|
||||||
|
> span {
|
||||||
|
height: $input-height;
|
||||||
|
font-size: $font-size-normal;
|
||||||
|
line-height: $input-height;
|
||||||
|
}
|
||||||
|
> :not(span) {
|
||||||
|
margin: ($offset / 2) 0;
|
||||||
|
}
|
||||||
|
&:after {
|
||||||
|
$size: ($input-height / 7);
|
||||||
|
$border: $size solid transparent;
|
||||||
|
position: absolute;
|
||||||
|
right: ($offset / 2);
|
||||||
|
bottom: $offset;
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
content: "";
|
||||||
|
border-top: $size solid $color-divider;
|
||||||
|
border-right: $border;
|
||||||
|
border-left: $border;
|
||||||
|
transition: transform $animation-duration $animation-curve-default;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ripple {
|
||||||
|
z-index: 0;
|
||||||
|
background-color: $color-divider;
|
||||||
|
}
|
|
@ -1,100 +0,0 @@
|
||||||
@import '../constants'
|
|
||||||
|
|
||||||
:local(.values)
|
|
||||||
z-index : 2
|
|
||||||
position : absolute
|
|
||||||
top : 0
|
|
||||||
left : -(OFFSET = (SPACE / 1.25))
|
|
||||||
right : -(OFFSET)
|
|
||||||
width : auto
|
|
||||||
height : 0
|
|
||||||
max-height : 50vh
|
|
||||||
list-style : none
|
|
||||||
opacity : 0
|
|
||||||
overflow : hidden
|
|
||||||
background-color : WHITE
|
|
||||||
border-radius : BORDER_RADIUS
|
|
||||||
transform : translateY(-(INPUT_HEIGHT / 2))
|
|
||||||
transition-property : height, box-shadow, opacity, transform
|
|
||||||
transition-duration : ANIMATION_DURATION
|
|
||||||
transition-timing-function : ANIMATION_EASE
|
|
||||||
> li
|
|
||||||
position : relative
|
|
||||||
padding : (SPACE / 2) OFFSET
|
|
||||||
opacity : 0
|
|
||||||
overflow : hidden
|
|
||||||
cursor : pointer
|
|
||||||
&.selected
|
|
||||||
color : PRIMARY
|
|
||||||
|
|
||||||
:local(.value)
|
|
||||||
display : block
|
|
||||||
> span
|
|
||||||
height : INPUT_HEIGHT
|
|
||||||
font-size : FONT_SIZE_NORMAL
|
|
||||||
line-height : INPUT_HEIGHT
|
|
||||||
> :not(span)
|
|
||||||
margin : (SPACE / 2) 0
|
|
||||||
&:after
|
|
||||||
SIZE = (INPUT_HEIGHT / 7)
|
|
||||||
position : absolute
|
|
||||||
content : ""
|
|
||||||
right : (SPACE / 2)
|
|
||||||
bottom : SPACE
|
|
||||||
width : 0
|
|
||||||
height : 0
|
|
||||||
border-left : BORDER = SIZE solid transparent
|
|
||||||
border-right : BORDER
|
|
||||||
border-top : SIZE solid DIVIDER
|
|
||||||
transition : transform ANIMATION_DURATION ANIMATION_EASE
|
|
||||||
|
|
||||||
:local(.root)
|
|
||||||
position : relative
|
|
||||||
margin-bottom : SPACE
|
|
||||||
width : inherit
|
|
||||||
color : TEXT
|
|
||||||
border-bottom : 1px solid DIVIDER
|
|
||||||
|
|
||||||
// -- Overrides
|
|
||||||
&.active
|
|
||||||
> label, > div
|
|
||||||
opacity : 0
|
|
||||||
transform : translateY((INPUT_HEIGHT / 4))
|
|
||||||
> div:after
|
|
||||||
transform : scale(0)
|
|
||||||
> ul
|
|
||||||
opacity : 1
|
|
||||||
transform : translateY(0%)
|
|
||||||
box-shadow : ZDEPTH_SHADOW_1
|
|
||||||
> li
|
|
||||||
opacity : 1
|
|
||||||
transition : opacity ANIMATION_DURATION ANIMATION_EASE
|
|
||||||
&:not(.active)
|
|
||||||
> *, > * > li
|
|
||||||
transition-delay : ANIMATION_DURATION
|
|
||||||
|
|
||||||
&.disabled
|
|
||||||
color : TEXT_SECONDARY
|
|
||||||
border-bottom-style : dotted
|
|
||||||
> div:after
|
|
||||||
transform : scale(0)
|
|
||||||
|
|
||||||
// -- Children
|
|
||||||
> *
|
|
||||||
width : 100%
|
|
||||||
> label, > div
|
|
||||||
transition-property : opacity, transform
|
|
||||||
transition-duration : ANIMATION_DURATION
|
|
||||||
transition-timing-function : ANIMATION_EASE
|
|
||||||
> label + ul
|
|
||||||
top : SPACE
|
|
||||||
> label
|
|
||||||
position : relative
|
|
||||||
bottom : -(SPACE / 4)
|
|
||||||
font-size : FONT_SIZE_TINY
|
|
||||||
color : TEXT_SECONDARY
|
|
||||||
|
|
||||||
:local(.ripple)
|
|
||||||
background-color : DIVIDER
|
|
||||||
opacity : 1
|
|
||||||
z-index : Z_INDEX_LOW
|
|
|
@ -10,4 +10,4 @@ var FontIcon = require('react-toolbox/components/font_icon');
|
||||||
|
|
||||||
| Name | Type | Default | Description|
|
| Name | Type | Default | Description|
|
||||||
|:- |:-: | :- |:-|
|
|:- |:-: | :- |:-|
|
||||||
| **value** | String | | The keyString for the icon you want representate.|
|
| **value** | String | | The keyString for the icon you want be displayed.|
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
/* global React */
|
import React from 'react';
|
||||||
|
import PureRenderMixin from 'react-addons-pure-render-mixin';
|
||||||
import { addons } from 'react/addons';
|
|
||||||
import style from './style';
|
import style from './style';
|
||||||
|
|
||||||
export default React.createClass({
|
export default React.createClass({
|
||||||
mixins: [addons.PureRenderMixin],
|
mixins: [PureRenderMixin],
|
||||||
|
|
||||||
displayName: 'FontIcon',
|
displayName: 'FontIcon',
|
||||||
|
|
||||||
|
@ -19,19 +18,13 @@ export default React.createClass({
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
onClick (event) {
|
|
||||||
if (this.props.onClick) {
|
|
||||||
this.props.onClick(event);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
|
let className = style[this.props.value];
|
||||||
|
if (this.props.className) className += ` ${this.props.className}`;
|
||||||
return (
|
return (
|
||||||
<span
|
<span data-react-toolbox='icon' {...this.props} className={className}>
|
||||||
data-react-toolbox='icon'
|
{this.props.children}
|
||||||
className={`${style.root} ${this.props.className} ${this.props.value}`}
|
</span>
|
||||||
onClick={this.props.onClick}
|
|
||||||
/>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,6 +1,6 @@
|
||||||
/* global React */
|
import React from 'react';
|
||||||
|
|
||||||
import { addons } from 'react/addons';
|
import PureRenderMixin from 'react-addons-pure-render-mixin';
|
||||||
import style from './style';
|
import style from './style';
|
||||||
import Autocomplete from '../autocomplete';
|
import Autocomplete from '../autocomplete';
|
||||||
import Dropdown from '../dropdown';
|
import Dropdown from '../dropdown';
|
||||||
|
@ -9,7 +9,7 @@ import Input from '../input';
|
||||||
import Switch from '../switch';
|
import Switch from '../switch';
|
||||||
|
|
||||||
export default React.createClass({
|
export default React.createClass({
|
||||||
mixins: [addons.PureRenderMixin],
|
mixins: [PureRenderMixin],
|
||||||
|
|
||||||
displayName: 'Form',
|
displayName: 'Form',
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
.root {
|
||||||
|
& > :last-child {
|
||||||
|
margin-bottom: 0 !important;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +0,0 @@
|
||||||
@import '../constants'
|
|
||||||
|
|
||||||
:local(.root)
|
|
||||||
& > :last-child
|
|
||||||
margin-bottom : 0 !important
|
|
|
@ -1,22 +1,25 @@
|
||||||
module.exports = {
|
module.exports = {
|
||||||
Aside: require('./aside'),
|
|
||||||
Autocomplete: require('./autocomplete'),
|
Autocomplete: require('./autocomplete'),
|
||||||
Button: require('./button'),
|
Button: require('./button'),
|
||||||
|
Calendar: require('./calendar'),
|
||||||
Card: require('./card'),
|
Card: require('./card'),
|
||||||
|
Checkbox: require('./checkbox'),
|
||||||
|
Clock: require('./clock'),
|
||||||
|
DatePicker: require('./date_picker'),
|
||||||
Dialog: require('./dialog'),
|
Dialog: require('./dialog'),
|
||||||
|
Drawer: require('./drawer'),
|
||||||
Dropdown: require('./dropdown'),
|
Dropdown: require('./dropdown'),
|
||||||
Fieldset: require('./fieldset'),
|
|
||||||
FontIcon: require('./font_icon'),
|
FontIcon: require('./font_icon'),
|
||||||
Form: require('./form'),
|
Form: require('./form'),
|
||||||
Input: require('./input'),
|
Input: require('./input'),
|
||||||
Link: require('./link'),
|
Link: require('./link'),
|
||||||
List: require('./list'),
|
List: require('./list'),
|
||||||
Loading: require('./loading'),
|
|
||||||
Navigation: require('./navigation'),
|
Navigation: require('./navigation'),
|
||||||
ProgressBar: require('./progress_bar'),
|
ProgressBar: require('./progress_bar'),
|
||||||
Ripple: require('./ripple'),
|
Ripple: require('./ripple'),
|
||||||
Slider: require('./slider'),
|
Slider: require('./slider'),
|
||||||
Switch: require('./switch'),
|
Switch: require('./switch'),
|
||||||
Tab: require('./tabs/tab'),
|
Tab: require('./tabs/tab'),
|
||||||
Tabs: require('./tabs/tabs')
|
Tabs: require('./tabs/tabs'),
|
||||||
|
TimePicker: require('./time_picker')
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
/* global React */
|
import React from 'react';
|
||||||
|
import PureRenderMixin from 'react-addons-pure-render-mixin';
|
||||||
import { addons } from 'react/addons';
|
import style from './style.scss';
|
||||||
import style from './style';
|
|
||||||
|
|
||||||
export default React.createClass({
|
export default React.createClass({
|
||||||
mixins: [addons.PureRenderMixin],
|
mixins: [PureRenderMixin],
|
||||||
|
|
||||||
displayName: 'Input',
|
displayName: 'Input',
|
||||||
|
|
||||||
|
@ -12,6 +11,7 @@ export default React.createClass({
|
||||||
className: React.PropTypes.string,
|
className: React.PropTypes.string,
|
||||||
disabled: React.PropTypes.bool,
|
disabled: React.PropTypes.bool,
|
||||||
error: React.PropTypes.string,
|
error: React.PropTypes.string,
|
||||||
|
floating: React.PropTypes.bool,
|
||||||
label: React.PropTypes.string,
|
label: React.PropTypes.string,
|
||||||
multiline: React.PropTypes.bool,
|
multiline: React.PropTypes.bool,
|
||||||
onBlur: React.PropTypes.func,
|
onBlur: React.PropTypes.func,
|
||||||
|
@ -27,6 +27,7 @@ export default React.createClass({
|
||||||
return {
|
return {
|
||||||
className: '',
|
className: '',
|
||||||
disabled: false,
|
disabled: false,
|
||||||
|
floating: true,
|
||||||
multiline: false,
|
multiline: false,
|
||||||
required: false,
|
required: false,
|
||||||
type: 'text'
|
type: 'text'
|
||||||
|
@ -34,121 +35,74 @@ export default React.createClass({
|
||||||
},
|
},
|
||||||
|
|
||||||
getInitialState () {
|
getInitialState () {
|
||||||
return {
|
return { value: this.props.value };
|
||||||
checked: this.props.value,
|
|
||||||
error: this.props.error,
|
|
||||||
touch: ['checkbox', 'radio'].indexOf(this.props.type) !== -1,
|
|
||||||
value: this.props.value,
|
|
||||||
focus: false,
|
|
||||||
valid: false
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
onBlur (event) {
|
|
||||||
this.setState({focus: false});
|
|
||||||
if (this.props.onBlur) this.props.onBlur(event, this);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
onChange (event) {
|
onChange (event) {
|
||||||
if (this.state.touch) {
|
this.setState({value: event.target.value}, () => {
|
||||||
this.setState({checked: event.target.checked, error: undefined});
|
if (this.props.onChange) this.props.onChange(event, this);
|
||||||
} else {
|
});
|
||||||
this.setState({value: event.target.value, error: undefined});
|
|
||||||
}
|
|
||||||
if (this.props.onChange) this.props.onChange(event, this);
|
|
||||||
},
|
|
||||||
|
|
||||||
onFocus (event) {
|
|
||||||
this.setState({focus: true});
|
|
||||||
if (this.props.onFocus) this.props.onFocus(event, this);
|
|
||||||
},
|
|
||||||
|
|
||||||
onKeyPress (event) {
|
|
||||||
this.setState({focus: true});
|
|
||||||
if (this.props.onKeyPress) this.props.onKeyPress(event, this);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
renderInput () {
|
renderInput () {
|
||||||
|
let className = style.input;
|
||||||
|
if (this.state.value && this.state.value.length > 0) className += ` ${style.filled}`;
|
||||||
|
|
||||||
if (this.props.multiline) {
|
if (this.props.multiline) {
|
||||||
return (
|
return (
|
||||||
<textarea
|
<textarea
|
||||||
ref='input'
|
ref='input'
|
||||||
|
role='input'
|
||||||
{...this.props}
|
{...this.props}
|
||||||
|
className={className}
|
||||||
onChange={this.onChange}
|
onChange={this.onChange}
|
||||||
onKeyPress={this.onKeyPress}
|
|
||||||
onFocus={this.onFocus}
|
|
||||||
onBlur={this.onBlur}
|
|
||||||
value={this.state.value} />
|
value={this.state.value} />
|
||||||
);
|
);
|
||||||
} else if (this.props.type === 'file') {
|
|
||||||
return (
|
|
||||||
<input
|
|
||||||
ref='input'
|
|
||||||
{...this.props}
|
|
||||||
value={undefined}
|
|
||||||
onChange={this.onChange} />
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
<input
|
<input
|
||||||
ref='input'
|
ref='input'
|
||||||
|
role='input'
|
||||||
{...this.props}
|
{...this.props}
|
||||||
|
className={className}
|
||||||
value={this.state.value}
|
value={this.state.value}
|
||||||
checked={this.state.checked}
|
onChange={this.onChange} />
|
||||||
onBlur={this.onBlur}
|
|
||||||
onChange={this.onChange}
|
|
||||||
onFocus={this.onFocus}
|
|
||||||
onKeyPress={this.onKeyPress} />
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
let className = `${style.root} ${this.props.className}`;
|
let className = style.root;
|
||||||
if (this.props.type) className += ` ${this.props.type}`;
|
let labelClassName = style.label;
|
||||||
if (this.state.checked) className += ' checked';
|
if (this.props.error) className += ` ${style.errored}`;
|
||||||
if (this.props.disabled) className += ' disabled';
|
if (this.props.disabled) className += ` ${style.disabled}`;
|
||||||
if (this.state.error) className += ' error';
|
if (this.props.className) className += ` ${this.props.className}`;
|
||||||
if (this.state.focus) className += ' focus';
|
if (this.props.type === 'hidden') className += ` ${style.hidden}`;
|
||||||
if (this.props.type === 'hidden') className += ' hidden';
|
if (!this.props.floating) labelClassName += ` ${style.fixed}`;
|
||||||
if (this.state.touch) className += ' touch';
|
|
||||||
if (this.props.type === 'radio') className += ' radio';
|
|
||||||
if (this.state.value && this.state.value.length > 0) className += ' valid';
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div data-react-toolbox='input' className={className}>
|
<div data-react-toolbox='input' className={className}>
|
||||||
{ this.renderInput() }
|
{ this.renderInput() }
|
||||||
<span className='bar'></span>
|
<span className={style.bar}></span>
|
||||||
{ this.props.label ? <label>{this.props.label}</label> : null }
|
{ this.props.label ? <label className={labelClassName}>{this.props.label}</label> : null }
|
||||||
{ this.state.error ? <span className='error'>{this.state.error}</span> : null }
|
{ this.props.error ? <span className={style.error}>{this.props.error}</span> : null }
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
blur () {
|
blur () {
|
||||||
this.refs.input.getDOMNode().blur();
|
this.refs.input.blur();
|
||||||
},
|
},
|
||||||
|
|
||||||
focus () {
|
focus () {
|
||||||
this.refs.input.getDOMNode().focus();
|
this.refs.input.focus();
|
||||||
},
|
},
|
||||||
|
|
||||||
getValue () {
|
getValue () {
|
||||||
if (this.props.type === 'file') {
|
return this.state.value;
|
||||||
return this.state.value;
|
|
||||||
} else if (this.refs.input) {
|
|
||||||
return this.refs.input.getDOMNode()[this.state.touch ? 'checked' : 'value'];
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
setError (data = 'Unknown error') {
|
setValue (value) {
|
||||||
this.setState({error: this.props.error || data});
|
this.setState({value: value});
|
||||||
},
|
|
||||||
|
|
||||||
setValue (argData) {
|
|
||||||
let data = this.state.touch && argData === undefined ? false : argData;
|
|
||||||
let attributes = { value: data };
|
|
||||||
if (this.state.touch && data) attributes.checked = data;
|
|
||||||
this.setState(attributes);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,125 @@
|
||||||
|
@import "../variables";
|
||||||
|
@import "../mixins";
|
||||||
|
|
||||||
|
$input-padding: 2 * $unit;
|
||||||
|
$input-field-height: 1.6 * $unit;
|
||||||
|
$input-field-padding: .8 * $unit;
|
||||||
|
$input-field-font-size: 1.6 * $unit;
|
||||||
|
$input-label-font-size: 1.2 * $unit;
|
||||||
|
$input-focus-label-top: .6 * $unit;
|
||||||
|
$input-text-background-color: transparent !default;
|
||||||
|
$input-text-label-color: unquote("rgba(#{$color-black}, 0.26)") !default;
|
||||||
|
$input-text-bottom-border-color: unquote("rgba(#{$color-black}, 0.12)") !default;
|
||||||
|
$input-text-highlight-color: unquote("rgb(#{$color-primary})") !default;
|
||||||
|
$input-text-disabled-color: $input-text-bottom-border-color !default;
|
||||||
|
$input-text-disabled-text-color: $input-text-label-color !default;
|
||||||
|
$input-text-error-color: unquote("rgb(222, 50, 38)") !default;
|
||||||
|
|
||||||
|
.root {
|
||||||
|
position: relative;
|
||||||
|
padding: $input-padding 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
padding: $input-field-padding 0;
|
||||||
|
font-size: $input-field-font-size;
|
||||||
|
color: $color-text;
|
||||||
|
background-color: $input-text-background-color;
|
||||||
|
border: 0;
|
||||||
|
border-bottom: 1px solid $input-text-bottom-border-color;
|
||||||
|
outline: none;
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
~ .bar:before, ~ .bar:after {
|
||||||
|
width: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
~ .label:not(.fixed) {
|
||||||
|
color: $input-text-highlight-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus, &.filled {
|
||||||
|
~ .label:not(.fixed) {
|
||||||
|
top: $input-focus-label-top;
|
||||||
|
font-size: $input-label-font-size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.filled ~ .label.fixed {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.label {
|
||||||
|
position: absolute;
|
||||||
|
top: $input-padding + $input-field-padding;
|
||||||
|
left: 0;
|
||||||
|
font-size: $input-field-font-size;
|
||||||
|
line-height: $input-field-font-size;
|
||||||
|
color: $input-text-label-color;
|
||||||
|
pointer-events: none;
|
||||||
|
transition-timing-function: $animation-curve-default;
|
||||||
|
transition-duration: $animation-duration;
|
||||||
|
transition-property: top, font-size, color;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bar {
|
||||||
|
position: relative;
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
&:before, &:after {
|
||||||
|
@include material-animation-default();
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
width: 0;
|
||||||
|
height: 2px;
|
||||||
|
content: "";
|
||||||
|
background-color: $input-text-highlight-color;
|
||||||
|
transition-property: width, background-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:before {
|
||||||
|
left: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:after {
|
||||||
|
right: 50%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.error {
|
||||||
|
font-size: $input-label-font-size;
|
||||||
|
line-height: 1.6 * $unit;
|
||||||
|
color: $input-text-error-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
.disabled > .input {
|
||||||
|
color: $input-text-disabled-text-color;
|
||||||
|
border-bottom-style: dotted;
|
||||||
|
}
|
||||||
|
|
||||||
|
.errored {
|
||||||
|
padding-bottom: 0;
|
||||||
|
|
||||||
|
> .input {
|
||||||
|
border-bottom-color: $input-text-error-color;
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
~ .label:not(.fixed) {
|
||||||
|
color: $input-text-error-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
~ .bar:before, ~ .bar:after {
|
||||||
|
background-color: $input-text-error-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
|
@ -1,171 +0,0 @@
|
||||||
@import '../constants'
|
|
||||||
|
|
||||||
:local(.root)
|
|
||||||
position : relative
|
|
||||||
margin-bottom : SPACE
|
|
||||||
input, textarea, label
|
|
||||||
font-size : FONT_SIZE_NORMAL
|
|
||||||
font-weight : FONT_WEIGHT_NORMAL
|
|
||||||
|
|
||||||
// -- Style
|
|
||||||
RADIUS = (SPACE / 8)
|
|
||||||
&.touch
|
|
||||||
// -- Children
|
|
||||||
input
|
|
||||||
pointer-events : all
|
|
||||||
z-index : 2
|
|
||||||
position : absolute
|
|
||||||
left : 0
|
|
||||||
width : 100%
|
|
||||||
height : 100%
|
|
||||||
opacity : 0
|
|
||||||
.bar, label
|
|
||||||
position : relative
|
|
||||||
display : inline-block
|
|
||||||
vertical-align : middle
|
|
||||||
.bar
|
|
||||||
width : SPACE
|
|
||||||
height : SPACE
|
|
||||||
margin-right : (SPACE / 1.32)
|
|
||||||
border-radius : RADIUS
|
|
||||||
box-shadow : inset 0 0 0 RADIUS TEXT
|
|
||||||
transition-property background-color, box-shadow
|
|
||||||
transition-duration ANIMATION_DURATION
|
|
||||||
transition-timing-function ANIMATION_EASE
|
|
||||||
&:before
|
|
||||||
z-index : -1
|
|
||||||
position : absolute
|
|
||||||
left : -(SPACE)
|
|
||||||
top : -(SPACE)
|
|
||||||
display : block
|
|
||||||
content : ""
|
|
||||||
width : SIZE = (3 * SPACE)
|
|
||||||
height : SIZE
|
|
||||||
border-radius : 50%
|
|
||||||
opacity : 0
|
|
||||||
&:after
|
|
||||||
display : block
|
|
||||||
width : SPACE
|
|
||||||
color : WHITE
|
|
||||||
text-align : center
|
|
||||||
transform scale(0)
|
|
||||||
transition transform ANIMATION_DURATION ANIMATION_DELAY ANIMATION_EASE
|
|
||||||
label
|
|
||||||
font-size : FONT_SIZE_SMALL
|
|
||||||
color : TEXT
|
|
||||||
// -- Style
|
|
||||||
&:not(.radio) .bar:after
|
|
||||||
content : "✓"
|
|
||||||
&.radio .bar
|
|
||||||
border-radius : 50%
|
|
||||||
&.disabled .bar
|
|
||||||
box-shadow inset 0 0 0 RADIUS DIVIDER
|
|
||||||
&.checked
|
|
||||||
&.radio .bar
|
|
||||||
box-shadow : inset 0 0 0 RADIUS ACCENT, inset 0 0 0 (RADIUS * 2.5) WHITE
|
|
||||||
&:not(.radio) .bar
|
|
||||||
box-shadow : none
|
|
||||||
.bar
|
|
||||||
background-color : ACCENT
|
|
||||||
&:before
|
|
||||||
background-color : alpha(ACCENT, .5)
|
|
||||||
animation-name ripple-touch
|
|
||||||
animation-iteration-count 1
|
|
||||||
animation-timing-function ANIMATION_EASE
|
|
||||||
animation-duration (2 * ANIMATION_DURATION)
|
|
||||||
&:after
|
|
||||||
transform scale(1)
|
|
||||||
|
|
||||||
&:not(.touch)
|
|
||||||
// -- Stylesheets
|
|
||||||
&.focus
|
|
||||||
input, textarea
|
|
||||||
outline : none
|
|
||||||
~ .bar:before, ~ .bar:after
|
|
||||||
width : 50%
|
|
||||||
&:invalid
|
|
||||||
& ~ label
|
|
||||||
color : CANCEL
|
|
||||||
& ~ .bar:before, & ~ .bar:after
|
|
||||||
background-color : CANCEL
|
|
||||||
&.focus , &.valid
|
|
||||||
input, textarea
|
|
||||||
& ~ label
|
|
||||||
top : -(SPACE / 2)
|
|
||||||
font-size : FONT_SIZE_TINY
|
|
||||||
color : PRIMARY
|
|
||||||
input[type="date"]
|
|
||||||
& ~ label
|
|
||||||
top : -(SPACE / 2)
|
|
||||||
font-size : FONT_SIZE_TINY
|
|
||||||
color : PRIMARY
|
|
||||||
&:not(.focus)
|
|
||||||
input, textarea
|
|
||||||
&:invalid:not(:required)
|
|
||||||
border-bottom-color : CANCEL
|
|
||||||
&.error
|
|
||||||
input, textarea
|
|
||||||
border-bottom-color : CANCEL
|
|
||||||
|
|
||||||
// -- Children
|
|
||||||
input, textarea
|
|
||||||
display : block
|
|
||||||
padding : (SPACE / 2) 0
|
|
||||||
width : 100%
|
|
||||||
color : TEXT
|
|
||||||
background-color : transparent
|
|
||||||
border : none
|
|
||||||
border-bottom : 1px solid DIVIDER
|
|
||||||
// -- Attributes
|
|
||||||
&:disabled
|
|
||||||
color : TEXT_SECONDARY
|
|
||||||
border-bottom-style : dotted
|
|
||||||
|
|
||||||
label
|
|
||||||
position : absolute
|
|
||||||
left : 0
|
|
||||||
top : (SPACE / 2)
|
|
||||||
color : TEXT_SECONDARY
|
|
||||||
transition-property top, font-size, color
|
|
||||||
transition-duration ANIMATION_DURATION
|
|
||||||
transition-timing-function ANIMATION_EASE
|
|
||||||
|
|
||||||
.bar
|
|
||||||
position : relative
|
|
||||||
display : block
|
|
||||||
width : 100%
|
|
||||||
&:before, &:after
|
|
||||||
content : ''
|
|
||||||
position : absolute
|
|
||||||
height : 2px
|
|
||||||
width : 0
|
|
||||||
bottom : 0
|
|
||||||
background-color : PRIMARY
|
|
||||||
transition-property width, background-color
|
|
||||||
transition-duration ANIMATION_DURATION
|
|
||||||
transition-timing-function ANIMATION_EASE
|
|
||||||
&:before
|
|
||||||
left : 50%
|
|
||||||
&:after
|
|
||||||
right : 50%
|
|
||||||
|
|
||||||
&.hidden
|
|
||||||
display : none
|
|
||||||
|
|
||||||
// -- Children
|
|
||||||
label
|
|
||||||
pointer-events : none
|
|
||||||
.error
|
|
||||||
position : absolute
|
|
||||||
right : (SPACE / 4)
|
|
||||||
bottom : -(SPACE / 1.25)
|
|
||||||
font-size : (FONT_SIZE_TINY * 0.9)
|
|
||||||
color : CANCEL
|
|
||||||
|
|
||||||
@keyframes ripple-touch
|
|
||||||
0%
|
|
||||||
transform scale(0)
|
|
||||||
opacity : 1
|
|
||||||
100%
|
|
||||||
transform scale(1)
|
|
||||||
opacity : 0
|
|
|
@ -1,11 +1,10 @@
|
||||||
/* global React */
|
import React from 'react';
|
||||||
|
import PureRenderMixin from 'react-addons-pure-render-mixin';
|
||||||
import { addons } from 'react/addons';
|
|
||||||
import style from './style';
|
import style from './style';
|
||||||
import FontIcon from '../font_icon';
|
import FontIcon from '../font_icon';
|
||||||
|
|
||||||
export default React.createClass({
|
export default React.createClass({
|
||||||
mixins: [addons.PureRenderMixin],
|
mixins: [PureRenderMixin],
|
||||||
|
|
||||||
displayName: 'Link',
|
displayName: 'Link',
|
||||||
|
|
||||||
|
@ -25,20 +24,16 @@ export default React.createClass({
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
onClick (event) {
|
|
||||||
if (this.props.onClick) {
|
|
||||||
this.props.onClick(event, this);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
|
let className = style.root;
|
||||||
|
if (this.props.className) className += ` ${this.props.className}`;
|
||||||
return (
|
return (
|
||||||
<a
|
<a
|
||||||
|
{...this.props}
|
||||||
data-react-toolbox='link'
|
data-react-toolbox='link'
|
||||||
data-flex='horizontal center'
|
data-flex='horizontal center'
|
||||||
href={`${this.props.route}`}
|
href={this.props.route}
|
||||||
className={`${style.root} ${this.props.className}`}
|
className={className}
|
||||||
onClick={this.onClick}
|
|
||||||
>
|
>
|
||||||
{ this.props.icon ? <FontIcon className={style.icon} value={this.props.icon} /> : null }
|
{ this.props.icon ? <FontIcon className={style.icon} value={this.props.icon} /> : null }
|
||||||
{ this.props.label ? <abbr>{this.props.label}</abbr> : null }
|
{ this.props.label ? <abbr>{this.props.label}</abbr> : null }
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
@import "../variables";
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
margin-right: $unit;
|
||||||
|
font-size: 1.8 * $unit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.root {
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
transition: opacity $animation-duration $animation-curve-default;
|
||||||
|
|
||||||
|
&:not(.active) {
|
||||||
|
font-weight: $font-weight-thin;
|
||||||
|
opacity: .5;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover, &:active {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
> * {
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
> abbr {
|
||||||
|
text-transform: capitalize;
|
||||||
|
}
|
||||||
|
|
||||||
|
> small {
|
||||||
|
font-size: $font-size-tiny;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,26 +0,0 @@
|
||||||
@import '../constants'
|
|
||||||
|
|
||||||
:local(.icon)
|
|
||||||
margin-right : (SPACE / 2)
|
|
||||||
font-size : FONT_SIZE_BIG
|
|
||||||
|
|
||||||
:local(.root)
|
|
||||||
position : relative
|
|
||||||
overflow : hidden
|
|
||||||
transition : opacity ANIMATION_DURATION ANIMATION_EASE
|
|
||||||
// -- Styles
|
|
||||||
&:not(.active)
|
|
||||||
font-weight : FONT_WEIGHT_THIN
|
|
||||||
opacity : 0.5
|
|
||||||
&:hover, &:active, &.active
|
|
||||||
opacity : 1
|
|
||||||
&.active
|
|
||||||
font-weight : FONT_WEIGHT_NORMAL
|
|
||||||
// -- Children
|
|
||||||
> *
|
|
||||||
vertical-align : middle
|
|
||||||
> abbr
|
|
||||||
text-transform : Capitalize
|
|
||||||
> small
|
|
||||||
font-size : FONT_SIZE_TINY
|
|
||||||
text-align : center
|
|
|
@ -1,17 +1,16 @@
|
||||||
/* global React */
|
import React from 'react';
|
||||||
|
import PureRenderMixin from 'react-addons-pure-render-mixin';
|
||||||
import { addons } from 'react/addons';
|
|
||||||
import style from './style';
|
import style from './style';
|
||||||
|
|
||||||
export default React.createClass({
|
export default React.createClass({
|
||||||
mixins: [addons.PureRenderMixin],
|
mixins: [PureRenderMixin],
|
||||||
|
|
||||||
displayName: 'List',
|
displayName: 'List',
|
||||||
|
|
||||||
propTypes: {
|
propTypes: {
|
||||||
className: React.PropTypes.string,
|
className: React.PropTypes.string,
|
||||||
dataSource: React.PropTypes.array,
|
dataSource: React.PropTypes.array,
|
||||||
ItemFactory: React.PropTypes.func,
|
template: React.PropTypes.func,
|
||||||
onClick: React.PropTypes.func,
|
onClick: React.PropTypes.func,
|
||||||
type: React.PropTypes.string
|
type: React.PropTypes.string
|
||||||
},
|
},
|
||||||
|
@ -38,7 +37,7 @@ export default React.createClass({
|
||||||
const items = this.props.dataSource.map((data, index) => {
|
const items = this.props.dataSource.map((data, index) => {
|
||||||
return (
|
return (
|
||||||
<li key={index} onClick={this.onClick.bind(null, data, index)}>
|
<li key={index} onClick={this.onClick.bind(null, data, index)}>
|
||||||
{this.props.itemFactory(data, index)}
|
{this.props.template(data, index)}
|
||||||
</li>
|
</li>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
@import "../variables";
|
||||||
|
|
||||||
|
$list-color: unquote("rgb(#{$color-black})") !default;
|
||||||
|
$list-background: unquote("rgb(#{$color-white})") !default;
|
||||||
|
|
||||||
|
.root {
|
||||||
|
list-style: none;
|
||||||
|
|
||||||
|
&, a {
|
||||||
|
color: $list-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
> li {
|
||||||
|
overflow: hidden;
|
||||||
|
background-color: $list-background;
|
||||||
|
box-shadow: $zdepth-shadow-1;
|
||||||
|
transition-timing-function: $animation-curve-default;
|
||||||
|
transition-duration: $animation-duration;
|
||||||
|
transition-property: box-shadow;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
box-shadow: $zdepth-shadow-2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,15 +0,0 @@
|
||||||
@import '../constants'
|
|
||||||
|
|
||||||
:local(.root)
|
|
||||||
list-style : none
|
|
||||||
&, a
|
|
||||||
color : TEXT
|
|
||||||
> li
|
|
||||||
overflow : hidden
|
|
||||||
background-color : WHITE
|
|
||||||
box-shadow : ZDEPTH_SHADOW_1
|
|
||||||
transition-property : box-shadow
|
|
||||||
transition-duration : ANIMATION_DURATION
|
|
||||||
transition-timing-function : ANIMATION_EASE
|
|
||||||
&:hover
|
|
||||||
box-shadow : ZDEPTH_SHADOW_2
|
|
|
@ -1,28 +0,0 @@
|
||||||
/* global React */
|
|
||||||
|
|
||||||
import { addons } from 'react/addons';
|
|
||||||
require('./style');
|
|
||||||
|
|
||||||
export default React.createClass({
|
|
||||||
mixins: [addons.PureRenderMixin],
|
|
||||||
|
|
||||||
displayName: 'Loading',
|
|
||||||
|
|
||||||
propTypes: {
|
|
||||||
type: React.PropTypes.string
|
|
||||||
},
|
|
||||||
|
|
||||||
getDefaultProps () {
|
|
||||||
return {
|
|
||||||
type: 'normal'
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
render () {
|
|
||||||
return (
|
|
||||||
<div data-component-loading={this.props.type} data-flex="vertical center">
|
|
||||||
<div></div><div></div><div></div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -1,13 +0,0 @@
|
||||||
# Loading
|
|
||||||
|
|
||||||
```
|
|
||||||
var Loading = require('react-toolbox/components/loading');
|
|
||||||
|
|
||||||
<Loading type='fullscreen' />
|
|
||||||
```
|
|
||||||
|
|
||||||
## Properties
|
|
||||||
|
|
||||||
| Name | Type | Default | Description|
|
|
||||||
|:- |:-: | :- |:-|
|
|
||||||
| **type** | String | normal | Type of the component, overwrite this property if you need set a different stylesheet.|
|
|
|
@ -1,41 +0,0 @@
|
||||||
@import '../constants'
|
|
||||||
|
|
||||||
[data-component-loading]
|
|
||||||
z-index : 2
|
|
||||||
> div
|
|
||||||
&::after
|
|
||||||
content : ""
|
|
||||||
position : absolute
|
|
||||||
transform scale(0.0)
|
|
||||||
SPEED = (3 * ANIMATION_DURATION)
|
|
||||||
&::after
|
|
||||||
border-radius : 50%
|
|
||||||
animation LOADING SPEED infinite
|
|
||||||
&:nth-child(1)::after
|
|
||||||
animation-delay (SPEED / 2.5)
|
|
||||||
&:nth-child(2)::after
|
|
||||||
animation-delay (SPEED / 5)
|
|
||||||
|
|
||||||
// -- Classes
|
|
||||||
&[data-component-loading="fullscreen"]
|
|
||||||
height : 100%
|
|
||||||
width : 100%
|
|
||||||
> div
|
|
||||||
width : SIZE = LOADING_HEIGHT
|
|
||||||
height : SIZE
|
|
||||||
&::after
|
|
||||||
content : ""
|
|
||||||
position : absolute
|
|
||||||
width : SIZE
|
|
||||||
height : SIZE
|
|
||||||
background-color : PRIMARY
|
|
||||||
transform scale(0.0)
|
|
||||||
&:nth-child(n+1)
|
|
||||||
margin-top : -(SIZE)
|
|
||||||
|
|
||||||
@keyframes LOADING
|
|
||||||
0%
|
|
||||||
transform scale(0.0)
|
|
||||||
100%
|
|
||||||
transform scale(1.0)
|
|
||||||
opacity: 0.1
|
|
|
@ -0,0 +1,279 @@
|
||||||
|
@import "./variables";
|
||||||
|
|
||||||
|
//-- Typography
|
||||||
|
@mixin typo-preferred-font($use-preferred: true) {
|
||||||
|
@if $use-preferred {
|
||||||
|
font-family: $preferred-font;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin typo-display-4($color-contrast: false, $use-preferred: true) {
|
||||||
|
@include typo-preferred-font($use-preferred);
|
||||||
|
font-size: 11.2rem;
|
||||||
|
font-weight: 300;
|
||||||
|
line-height: 1;
|
||||||
|
letter-spacing: -.04em;
|
||||||
|
|
||||||
|
@if $color-contrast {
|
||||||
|
opacity: .54;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin typo-display-3($color-contrast: false, $use-preferred: true) {
|
||||||
|
@include typo-preferred-font($use-preferred);
|
||||||
|
font-size: 5.6rem;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 1.35;
|
||||||
|
letter-spacing: -.02em;
|
||||||
|
|
||||||
|
@if $color-contrast {
|
||||||
|
opacity: .54;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin typo-display-2($color-contrast: false, $use-preferred: true) {
|
||||||
|
@include typo-preferred-font($use-preferred);
|
||||||
|
font-size: 4.5rem;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 4.8rem;
|
||||||
|
|
||||||
|
@if $color-contrast {
|
||||||
|
opacity: .54;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin typo-display-1($color-contrast: false, $use-preferred: true) {
|
||||||
|
@include typo-preferred-font($use-preferred);
|
||||||
|
font-size: 3.4rem;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 4rem;
|
||||||
|
|
||||||
|
@if $color-contrast {
|
||||||
|
opacity: .54;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin typo-headline($color-contrast: false, $use-preferred: true) {
|
||||||
|
@include typo-preferred-font($use-preferred);
|
||||||
|
font-size: 2.4rem;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 3.2rem;
|
||||||
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
|
||||||
|
@if $color-contrast {
|
||||||
|
opacity: .87;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin typo-title($color-contrast: false, $use-preferred: true) {
|
||||||
|
@include typo-preferred-font($use-preferred);
|
||||||
|
font-size: 2rem;
|
||||||
|
font-weight: 500;
|
||||||
|
line-height: 1;
|
||||||
|
letter-spacing: .02em;
|
||||||
|
|
||||||
|
@if $color-contrast {
|
||||||
|
opacity: .87;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin typo-subhead($color-contrast: false, $use-preferred: true) {
|
||||||
|
@include typo-preferred-font($use-preferred);
|
||||||
|
font-size: 1.6rem;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 2.4rem;
|
||||||
|
letter-spacing: .04em;
|
||||||
|
|
||||||
|
@if $color-contrast {
|
||||||
|
opacity: .87;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin typo-subhead-2($color-contrast: false, $use-preferred: true) {
|
||||||
|
@include typo-preferred-font($use-preferred);
|
||||||
|
font-size: 1.6rem;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 2.8rem;
|
||||||
|
letter-spacing: .04em;
|
||||||
|
|
||||||
|
@if $color-contrast {
|
||||||
|
opacity: .87;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin typo-body-2($color-contrast: false, $use-preferred: false) {
|
||||||
|
@include typo-preferred-font($use-preferred);
|
||||||
|
font-size: 1.4rem;
|
||||||
|
line-height: 2.4rem;
|
||||||
|
letter-spacing: 0;
|
||||||
|
|
||||||
|
@if $use-preferred {
|
||||||
|
font-weight: 500;
|
||||||
|
} @else {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
@if $color-contrast {
|
||||||
|
opacity: .87;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin typo-body-1($color-contrast: false, $use-preferred: false) {
|
||||||
|
@include typo-preferred-font($use-preferred);
|
||||||
|
font-size: 1.4rem;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 2.4rem;
|
||||||
|
letter-spacing: 0;
|
||||||
|
|
||||||
|
@if $color-contrast {
|
||||||
|
opacity: .87;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin typo-caption($color-contrast: false, $use-preferred: false) {
|
||||||
|
@include typo-preferred-font($use-preferred);
|
||||||
|
font-size: 1.2rem;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 1;
|
||||||
|
letter-spacing: 0;
|
||||||
|
|
||||||
|
@if $color-contrast {
|
||||||
|
opacity: .54;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin typo-blockquote($color-contrast: false, $use-preferred: true) {
|
||||||
|
@include typo-preferred-font($use-preferred);
|
||||||
|
position: relative;
|
||||||
|
font-size: 2.4rem;
|
||||||
|
font-style: italic;
|
||||||
|
font-weight: 300;
|
||||||
|
line-height: 1.35;
|
||||||
|
letter-spacing: .08em;
|
||||||
|
|
||||||
|
&:before {
|
||||||
|
position: absolute;
|
||||||
|
left: -.5em;
|
||||||
|
content: "“";
|
||||||
|
}
|
||||||
|
|
||||||
|
&:after {
|
||||||
|
margin-left: -.05em;
|
||||||
|
content: "”";
|
||||||
|
}
|
||||||
|
|
||||||
|
@if $color-contrast {
|
||||||
|
opacity: .54;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin typo-menu($color-contrast: false, $use-preferred: true) {
|
||||||
|
@include typo-preferred-font($use-preferred);
|
||||||
|
font-size: 1.4rem;
|
||||||
|
font-weight: 500;
|
||||||
|
line-height: 1;
|
||||||
|
letter-spacing: 0;
|
||||||
|
|
||||||
|
@if $color-contrast {
|
||||||
|
opacity: .87;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin typo-button($color-contrast: false, $use-preferred: true) {
|
||||||
|
@include typo-preferred-font($use-preferred);
|
||||||
|
font-size: 1.4rem;
|
||||||
|
font-weight: 500;
|
||||||
|
line-height: 1;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0;
|
||||||
|
|
||||||
|
@if $color-contrast {
|
||||||
|
opacity: .87;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-- Shadows
|
||||||
|
@mixin focus-shadow() {
|
||||||
|
box-shadow: 0 0 8px rgba(0, 0, 0, .18), 0 8px 16px rgba(0, 0, 0, .36);
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin shadow-2dp() {
|
||||||
|
box-shadow: 0 2px 2px 0 rgba(0, 0, 0, $shadow-key-penumbra-opacity),
|
||||||
|
0 3px 1px -2px rgba(0, 0, 0, $shadow-key-umbra-opacity),
|
||||||
|
0 1px 5px 0 rgba(0, 0, 0, $shadow-ambient-shadow-opacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin shadow-3dp() {
|
||||||
|
box-shadow: 0 3px 4px 0 rgba(0, 0, 0, $shadow-key-penumbra-opacity),
|
||||||
|
0 3px 3px -2px rgba(0, 0, 0, $shadow-key-umbra-opacity),
|
||||||
|
0 1px 8px 0 rgba(0, 0, 0, $shadow-ambient-shadow-opacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin shadow-4dp() {
|
||||||
|
box-shadow: 0 4px 5px 0 rgba(0, 0, 0, $shadow-key-penumbra-opacity),
|
||||||
|
0 1px 10px 0 rgba(0, 0, 0, $shadow-ambient-shadow-opacity),
|
||||||
|
0 2px 4px -1px rgba(0, 0, 0, $shadow-key-umbra-opacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin shadow-6dp() {
|
||||||
|
box-shadow: 0 6px 10px 0 rgba(0, 0, 0, $shadow-key-penumbra-opacity),
|
||||||
|
0 1px 18px 0 rgba(0, 0, 0, $shadow-ambient-shadow-opacity),
|
||||||
|
0 3px 5px -1px rgba(0, 0, 0, $shadow-key-umbra-opacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin shadow-8dp() {
|
||||||
|
box-shadow: 0 8px 10px 1px rgba(0, 0, 0, $shadow-key-penumbra-opacity),
|
||||||
|
0 3px 14px 2px rgba(0, 0, 0, $shadow-ambient-shadow-opacity),
|
||||||
|
0 5px 5px -3px rgba(0, 0, 0, $shadow-key-umbra-opacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin shadow-16dp() {
|
||||||
|
box-shadow: 0 16px 24px 2px rgba(0, 0, 0, $shadow-key-penumbra-opacity),
|
||||||
|
0 6px 30px 5px rgba(0, 0, 0, $shadow-ambient-shadow-opacity),
|
||||||
|
0 8px 10px -5px rgba(0, 0, 0, $shadow-key-umbra-opacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
//-- Animations
|
||||||
|
@mixin material-animation-fast-out-slow-in($duration: .2s) {
|
||||||
|
transition-timing-function: $animation-curve-fast-out-slow-in;
|
||||||
|
transition-duration: $duration;
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin material-animation-linear-out-slow-in($duration: .2s) {
|
||||||
|
transition-timing-function: $animation-curve-linear-out-slow-in;
|
||||||
|
transition-duration: $duration;
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin material-animation-fast-out-linear-in($duration: .2s) {
|
||||||
|
transition-timing-function: $animation-curve-fast-out-linear-in;
|
||||||
|
transition-duration: $duration;
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin material-animation-default($duration: .2s) {
|
||||||
|
transition-timing-function: $animation-curve-default;
|
||||||
|
transition-duration: $duration;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The frames are this way to prevent a flicker in Safari
|
||||||
|
// See https://goo.gl/5luFDk
|
||||||
|
@mixin ripple-loading($name, $width, $height, $opacity: 0.3) {
|
||||||
|
@keyframes #{$name} {
|
||||||
|
0% {
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
opacity: $opacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
95% {
|
||||||
|
width: $width;
|
||||||
|
height: $height;
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,12 +1,11 @@
|
||||||
/* global React */
|
import React from 'react';
|
||||||
|
import PureRenderMixin from 'react-addons-pure-render-mixin';
|
||||||
import { addons } from 'react/addons';
|
|
||||||
import style from './style';
|
import style from './style';
|
||||||
import Button from '../button';
|
import Button from '../button';
|
||||||
import Link from '../link';
|
import Link from '../link';
|
||||||
|
|
||||||
export default React.createClass({
|
export default React.createClass({
|
||||||
mixins: [addons.PureRenderMixin],
|
mixins: [PureRenderMixin],
|
||||||
|
|
||||||
displayName: 'Navigation',
|
displayName: 'Navigation',
|
||||||
|
|
||||||
|
@ -27,8 +26,8 @@ export default React.createClass({
|
||||||
},
|
},
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
let className = `${style.root} ${this.props.className}`;
|
let className = `${style[this.props.type]}`;
|
||||||
if (this.props.type) className += ` ${this.props.type}`;
|
if (this.props.className) className += ` ${this.props.className}`;
|
||||||
|
|
||||||
const buttons = this.props.actions.map((action, index) => {
|
const buttons = this.props.actions.map((action, index) => {
|
||||||
return <Button key={index} {...action} />;
|
return <Button key={index} {...action} />;
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
@import "../variables";
|
||||||
|
|
||||||
|
$navigation-space: $unit;
|
||||||
|
$navigation-color: unquote("rgb(#{$color-black})") !default;
|
||||||
|
$navigation-background: unquote("rgb(#{$color-white})") !default;
|
||||||
|
|
||||||
|
.horizontal {
|
||||||
|
> * {
|
||||||
|
display: inline-block;
|
||||||
|
margin-right: $navigation-space;
|
||||||
|
font-size: $font-size-normal;
|
||||||
|
font-weight: $font-weight-normal;
|
||||||
|
color: $navigation-color;
|
||||||
|
|
||||||
|
> small {
|
||||||
|
padding: 0 $navigation-space;
|
||||||
|
margin-left: $navigation-space;
|
||||||
|
font-weight: $font-weight-bold;
|
||||||
|
color: $navigation-color;
|
||||||
|
background-color: $navigation-background;
|
||||||
|
border-radius: $navigation-space;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.vertical {
|
||||||
|
> * {
|
||||||
|
display: block;
|
||||||
|
padding: 0 $navigation-space;
|
||||||
|
line-height: $unit;
|
||||||
|
transition-property: box-shadow, opacity;
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
box-shadow: inset 10 * $unit 0 $navigation-background;
|
||||||
|
}
|
||||||
|
|
||||||
|
> small {
|
||||||
|
float: right;
|
||||||
|
opacity: .5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.default {
|
||||||
|
@extend .horizontal;
|
||||||
|
}
|
|
@ -1,29 +0,0 @@
|
||||||
@import '../constants'
|
|
||||||
|
|
||||||
:local(.root)
|
|
||||||
&.horizontal
|
|
||||||
> *
|
|
||||||
display : inline-block
|
|
||||||
margin-right : SPACE
|
|
||||||
color : WHITE
|
|
||||||
font-size : FONT_SIZE_SMALL
|
|
||||||
font-weight : FONT_WEIGHT_NORMAL !important
|
|
||||||
> small
|
|
||||||
margin-left : SIZE = (SPACE / 5)
|
|
||||||
padding : 0 SIZE
|
|
||||||
font-weight : FONT_WEIGHT_BOLD
|
|
||||||
color : BACKGROUND_DARK
|
|
||||||
background-color : WHITE
|
|
||||||
border-radius : SIZE
|
|
||||||
|
|
||||||
&.vertical
|
|
||||||
> *
|
|
||||||
display : block
|
|
||||||
padding : 0 SPACE
|
|
||||||
line-height : UNIT
|
|
||||||
transition-property box-shadow, opacity
|
|
||||||
&.active
|
|
||||||
box-shadow inset MENU_WIDTH 0 BACKGROUND
|
|
||||||
> small
|
|
||||||
float : right
|
|
||||||
opacity : 0.5
|
|
|
@ -1,149 +0,0 @@
|
||||||
// normalize v3.0.2 | MIT License | git.io/normalize
|
|
||||||
|
|
||||||
html
|
|
||||||
font-family sans-serif
|
|
||||||
-ms-text-size-adjust 100%
|
|
||||||
-webkit-text-size-adjust 100%
|
|
||||||
|
|
||||||
body
|
|
||||||
margin 0
|
|
||||||
|
|
||||||
article, aside, details, figcaption, figure, footer, header, hgroup, main, menu,
|
|
||||||
nav, section, summary
|
|
||||||
display block
|
|
||||||
|
|
||||||
audio, canvas, progress, video
|
|
||||||
display inline-block
|
|
||||||
vertical-align baseline
|
|
||||||
|
|
||||||
audio
|
|
||||||
&:not([controls])
|
|
||||||
display none
|
|
||||||
height 0
|
|
||||||
|
|
||||||
[hidden], template
|
|
||||||
display none
|
|
||||||
|
|
||||||
a
|
|
||||||
background-color transparent
|
|
||||||
&:active, &:hover
|
|
||||||
outline 0
|
|
||||||
|
|
||||||
abbr[title]
|
|
||||||
border-bottom 1px dotted
|
|
||||||
|
|
||||||
b, strong
|
|
||||||
font-weight bold
|
|
||||||
|
|
||||||
dfn
|
|
||||||
font-style italic
|
|
||||||
|
|
||||||
h1
|
|
||||||
font-size 2em
|
|
||||||
margin 0.67em 0
|
|
||||||
|
|
||||||
mark
|
|
||||||
background #ff0
|
|
||||||
color #000
|
|
||||||
|
|
||||||
small
|
|
||||||
font-size 80%
|
|
||||||
|
|
||||||
sub, sup
|
|
||||||
font-size 75%
|
|
||||||
line-height 0
|
|
||||||
position relative
|
|
||||||
vertical-align baseline
|
|
||||||
|
|
||||||
sup
|
|
||||||
top -0.5em
|
|
||||||
|
|
||||||
sub
|
|
||||||
bottom -0.25em
|
|
||||||
|
|
||||||
img
|
|
||||||
border: 0
|
|
||||||
|
|
||||||
svg
|
|
||||||
&:not(:root)
|
|
||||||
overflow hidden
|
|
||||||
|
|
||||||
figure
|
|
||||||
border: 0
|
|
||||||
|
|
||||||
hr
|
|
||||||
-moz-box-sizing content-box
|
|
||||||
box-sizing content-box
|
|
||||||
height 0
|
|
||||||
|
|
||||||
pre
|
|
||||||
overflow auto
|
|
||||||
|
|
||||||
code, kbd, pre, samp
|
|
||||||
font-family monospace, monospace
|
|
||||||
font-size 1em
|
|
||||||
|
|
||||||
button, input, optgroup, select, textarea
|
|
||||||
color inherit
|
|
||||||
font inherit
|
|
||||||
margin 0
|
|
||||||
|
|
||||||
button
|
|
||||||
overflow visible
|
|
||||||
|
|
||||||
button, select
|
|
||||||
text-transform none
|
|
||||||
|
|
||||||
button, html input[type="button"], input[type="reset"], input[type="submit"]
|
|
||||||
-webkit-appearance button
|
|
||||||
cursor pointer
|
|
||||||
|
|
||||||
button[disabled], html input[disabled]
|
|
||||||
cursor default
|
|
||||||
|
|
||||||
button::-moz-focus-inner, input::-moz-focus-inner
|
|
||||||
border 0
|
|
||||||
padding 0
|
|
||||||
|
|
||||||
input
|
|
||||||
line-height normal
|
|
||||||
|
|
||||||
input[type="checkbox"], input[type="radio"]
|
|
||||||
box-sizing border-box
|
|
||||||
padding 0
|
|
||||||
|
|
||||||
input[type="number"]::-webkit-inner-spin-button,
|
|
||||||
input[type="number"]::-webkit-outer-spin-button
|
|
||||||
height auto
|
|
||||||
|
|
||||||
input[type="search"]
|
|
||||||
-webkit-appearance textfield
|
|
||||||
-moz-box-sizing content-box
|
|
||||||
-webkit-box-sizing content-box
|
|
||||||
box-sizing content-box
|
|
||||||
|
|
||||||
input[type="search"]::-webkit-search-cancel-button,
|
|
||||||
input[type="search"]::-webkit-search-decoration
|
|
||||||
-webkit-appearance none
|
|
||||||
|
|
||||||
fieldset
|
|
||||||
border 1px solid #c0c0c0
|
|
||||||
margin 0 2px
|
|
||||||
padding 0.35em 0.625em 0.75em
|
|
||||||
|
|
||||||
legend
|
|
||||||
border 0
|
|
||||||
padding 0
|
|
||||||
|
|
||||||
textarea
|
|
||||||
overflow auto
|
|
||||||
|
|
||||||
optgroup
|
|
||||||
font-weight bold
|
|
||||||
|
|
||||||
table
|
|
||||||
border-collapse collapse
|
|
||||||
border-spacing 0
|
|
||||||
|
|
||||||
td, th
|
|
||||||
padding 0
|
|
|
@ -1,4 +1,5 @@
|
||||||
import expect from 'expect';
|
import expect from 'expect';
|
||||||
|
import style from '../../progress_bar/style';
|
||||||
import utils from '../../utils/testing';
|
import utils from '../../utils/testing';
|
||||||
import ProgressBar from '../index';
|
import ProgressBar from '../index';
|
||||||
|
|
||||||
|
@ -56,8 +57,8 @@ describe('ProgressBar', function () {
|
||||||
|
|
||||||
it('contains mode and className in its className', function () {
|
it('contains mode and className in its className', function () {
|
||||||
progressBar = utils.shallowRenderComponent(ProgressBar, {mode: 'determinate', className: 'tight'});
|
progressBar = utils.shallowRenderComponent(ProgressBar, {mode: 'determinate', className: 'tight'});
|
||||||
expect(progressBar.props.className).toContain('determinate');
|
expect(progressBar.props.className).toContain(style.determinate);
|
||||||
expect(progressBar.props.className).toContain('tight');
|
expect(progressBar.props.className).toContain(style.tight);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
/* global React */
|
import React from 'react';
|
||||||
|
import PureRenderMixin from 'react-addons-pure-render-mixin';
|
||||||
import { addons } from 'react/addons';
|
import style from './style';
|
||||||
import css from './style';
|
|
||||||
import prefixer from '../utils/prefixer';
|
import prefixer from '../utils/prefixer';
|
||||||
|
|
||||||
export default React.createClass({
|
export default React.createClass({
|
||||||
mixins: [addons.PureRenderMixin],
|
mixins: [PureRenderMixin],
|
||||||
|
|
||||||
propTypes: {
|
propTypes: {
|
||||||
buffer: React.PropTypes.number,
|
buffer: React.PropTypes.number,
|
||||||
|
@ -45,8 +44,8 @@ export default React.createClass({
|
||||||
|
|
||||||
renderCircular () {
|
renderCircular () {
|
||||||
return (
|
return (
|
||||||
<svg className={css.circle}>
|
<svg className={style.circle}>
|
||||||
<circle className={css.circlePath} style={this.circularStyle()} cx="30" cy="30" r="25" />
|
<circle className={style.path} style={this.circularStyle()} cx='30' cy='30' r='25' />
|
||||||
</svg>
|
</svg>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
@ -66,26 +65,27 @@ export default React.createClass({
|
||||||
const {buffer, value} = this.linearStyle();
|
const {buffer, value} = this.linearStyle();
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<span ref="buffer" data-ref="buffer" className={css.bufferBar} style={buffer}></span>
|
<span ref='buffer' data-ref='buffer' className={style.buffer} style={buffer}></span>
|
||||||
<span ref="value" data-ref="value" className={css.valueBar} style={value}></span>
|
<span ref='value' data-ref='value' className={style.value} style={value}></span>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
let className = this.props.type === 'linear' ? css.linearBar : css.circularBar;
|
let className = this.props.type === 'linear' ? style.linear : style.circular;
|
||||||
|
if (this.props.mode) className += ` ${style[this.props.mode]}`;
|
||||||
|
if (this.props.multicolor) className += ` ${style.multicolor}`;
|
||||||
if (this.props.className) className += ` ${this.props.className}`;
|
if (this.props.className) className += ` ${this.props.className}`;
|
||||||
if (this.props.mode) className += ` ${this.props.mode}`;
|
|
||||||
if (this.props.multicolor) className += ` multicolor`;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
data-react-toolbox='progress-bar'
|
||||||
className={className}
|
className={className}
|
||||||
role="progressbar"
|
|
||||||
aria-valuenow={this.props.value}
|
aria-valuenow={this.props.value}
|
||||||
aria-valuemin={this.props.min}
|
aria-valuemin={this.props.min}
|
||||||
aria-valuemax={this.props.max}>
|
aria-valuemax={this.props.max}
|
||||||
{ this.props.type === 'circular' ? this.renderCircular() : this.renderLinear() }
|
>
|
||||||
|
{ this.props.type === 'circular' ? this.renderCircular() : this.renderLinear() }
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,143 @@
|
||||||
|
@import "../variables";
|
||||||
|
|
||||||
|
$progress-height: .4 * $unit;
|
||||||
|
$progress-main-color: unquote("rgb(#{$color-primary})") !default;
|
||||||
|
$progress-secondary-color: unquote("rgba(#{$color-primary-contrast}, 0.7)") !default;
|
||||||
|
$circle-wrapper-width: 60;
|
||||||
|
$circle-radius: 25;
|
||||||
|
$scale-ratio: $circle-radius / 20;
|
||||||
|
|
||||||
|
.linear {
|
||||||
|
position: relative;
|
||||||
|
display: inline-block;
|
||||||
|
width: 100%;
|
||||||
|
height: $progress-height;
|
||||||
|
overflow: hidden;
|
||||||
|
background: $color-divider;
|
||||||
|
|
||||||
|
&.indeterminate .value {
|
||||||
|
transform-origin: center center;
|
||||||
|
animation: linear-indeterminate-bar 1s linear infinite;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.value, .buffer {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
transition-timing-function: $animation-curve-default;
|
||||||
|
transition-duration: $animation-duration;
|
||||||
|
transform: scaleX(0);
|
||||||
|
transform-origin: left center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.value {
|
||||||
|
background-color: $progress-main-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
.buffer {
|
||||||
|
background-image: linear-gradient(to right, $progress-secondary-color, $progress-secondary-color),
|
||||||
|
linear-gradient(to right, $progress-main-color, $progress-main-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.circular {
|
||||||
|
position: relative;
|
||||||
|
display: inline-block;
|
||||||
|
width: $circle-wrapper-width * 1px;
|
||||||
|
height: $circle-wrapper-width * 1px;
|
||||||
|
transform: rotate(-90deg);
|
||||||
|
|
||||||
|
&.indeterminate {
|
||||||
|
.circle {
|
||||||
|
animation: circular-indeterminate-bar-rotate 2s linear infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
.path {
|
||||||
|
animation: circular-indeterminate-bar-dash 1.5s ease-in-out infinite;
|
||||||
|
stroke-dasharray: $scale-ratio * 1, $scale-ratio * 200;
|
||||||
|
stroke-dashoffset: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.multicolor .path {
|
||||||
|
animation: circular-indeterminate-bar-dash 1.5s ease-in-out infinite,
|
||||||
|
colors (1.5s * 4) ease-in-out infinite;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.circle {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.path {
|
||||||
|
transition: stroke-dasharray $animation-duration $animation-curve-default;
|
||||||
|
stroke-dasharray: 0, $scale-ratio * 200;
|
||||||
|
stroke-dashoffset: 0;
|
||||||
|
stroke-linecap: round;
|
||||||
|
stroke-miterlimit: 20;
|
||||||
|
stroke-width: 4;
|
||||||
|
stroke: $progress-main-color;
|
||||||
|
fill: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes linear-indeterminate-bar {
|
||||||
|
0% {
|
||||||
|
transform: translate(-50%) scaleX(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
50% {
|
||||||
|
transform: translate(-0%) scaleX(.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
transform: translate(50%) scaleX(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes circular-indeterminate-bar-rotate {
|
||||||
|
100% {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes circular-indeterminate-bar-dash {
|
||||||
|
0% {
|
||||||
|
stroke-dasharray: $scale-ratio * 1, $scale-ratio * 200;
|
||||||
|
stroke-dashoffset: $scale-ratio * 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
50% {
|
||||||
|
stroke-dasharray: $scale-ratio * 89, $scale-ratio * 200;
|
||||||
|
stroke-dashoffset: $scale-ratio * -35;
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
stroke-dasharray: $scale-ratio * 89, $scale-ratio * 200;
|
||||||
|
stroke-dashoffset: $scale-ratio * -124;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes colors {
|
||||||
|
0% {
|
||||||
|
stroke: #4285f4;
|
||||||
|
}
|
||||||
|
|
||||||
|
25% {
|
||||||
|
stroke: #de3e35;
|
||||||
|
}
|
||||||
|
|
||||||
|
50% {
|
||||||
|
stroke: #f7c223;
|
||||||
|
}
|
||||||
|
|
||||||
|
75% {
|
||||||
|
stroke: #1b9a59;
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
stroke: #4285f4;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,105 +0,0 @@
|
||||||
@import '../constants'
|
|
||||||
|
|
||||||
CIRCLE_WRAPPER_WIDTH = 60 // You need to change cx and cy in markup too
|
|
||||||
CIRCLE_RADIUS = 25 // You need to change r in the markup too
|
|
||||||
SCALE_RATIO = CIRCLE_RADIUS/20
|
|
||||||
|
|
||||||
// -- Linear progress bar
|
|
||||||
:local(.linearBar)
|
|
||||||
display : inline-block
|
|
||||||
position : relative
|
|
||||||
height : PROGRESS_BAR_HEIGHT
|
|
||||||
width : 100%
|
|
||||||
background : darken(BACKGROUND, 7.5%)
|
|
||||||
overflow : hidden
|
|
||||||
|
|
||||||
:local(.valueBar), :local(.bufferBar)
|
|
||||||
position : absolute
|
|
||||||
bottom : 0
|
|
||||||
left : 0
|
|
||||||
right : 0
|
|
||||||
top : 0
|
|
||||||
transform : scaleX(0)
|
|
||||||
transform-origin : left center
|
|
||||||
transition-duration : ANIMATION_DURATION
|
|
||||||
transition-timing-function : ANIMATION_EASE
|
|
||||||
|
|
||||||
:local(.valueBar)
|
|
||||||
background-color : ACCENT
|
|
||||||
|
|
||||||
:local(.bufferBar)
|
|
||||||
background-color : alpha(ACCENT, 15%)
|
|
||||||
|
|
||||||
:local(.linearBar).indeterminate :local(.valueBar)
|
|
||||||
transform-origin : center center
|
|
||||||
animation : linear-indeterminate-bar 1s linear infinite
|
|
||||||
|
|
||||||
// -- Circular progress bar
|
|
||||||
:local(.circularBar)
|
|
||||||
display : inline-block
|
|
||||||
position : relative
|
|
||||||
height : CIRCLE_WRAPPER_WIDTH * 1px
|
|
||||||
width : CIRCLE_WRAPPER_WIDTH * 1px
|
|
||||||
transform : rotate(-90deg)
|
|
||||||
|
|
||||||
:local(.circle)
|
|
||||||
height : 100%
|
|
||||||
width : 100%
|
|
||||||
|
|
||||||
:local(.circlePath)
|
|
||||||
stroke-dasharray : 0, SCALE_RATIO * 200
|
|
||||||
stroke-dashoffset : 0
|
|
||||||
stroke-linecap : round
|
|
||||||
stroke-miterlimit : 20
|
|
||||||
stroke-width : 4
|
|
||||||
stroke : ACCENT
|
|
||||||
fill : none
|
|
||||||
transition : stroke-dasharray ANIMATION_DURATION ANIMATION_EASE
|
|
||||||
|
|
||||||
:local(.circularBar).indeterminate
|
|
||||||
:local(.circle)
|
|
||||||
animation : circular-indeterminate-bar-rotate 2s linear infinite
|
|
||||||
|
|
||||||
:local(.circlePath)
|
|
||||||
stroke-dasharray : SCALE_RATIO * 1, SCALE_RATIO * 200
|
|
||||||
stroke-dashoffset : 0
|
|
||||||
animation : circular-indeterminate-bar-dash 1.5s ease-in-out infinite
|
|
||||||
|
|
||||||
&.multicolor :local(.circlePath)
|
|
||||||
animation : circular-indeterminate-bar-dash 1.5s ease-in-out infinite, colors (1.5s*4) ease-in-out infinite
|
|
||||||
|
|
||||||
// -- Animations
|
|
||||||
@keyframes linear-indeterminate-bar
|
|
||||||
0%
|
|
||||||
transform : translate(-50%) scaleX(0)
|
|
||||||
50%
|
|
||||||
transform : translate(-0%) scaleX(0.3)
|
|
||||||
100%
|
|
||||||
transform : translate(50%) scaleX(0)
|
|
||||||
|
|
||||||
@keyframes circular-indeterminate-bar-rotate
|
|
||||||
100%
|
|
||||||
transform : rotate(360deg)
|
|
||||||
|
|
||||||
@keyframes circular-indeterminate-bar-dash
|
|
||||||
0%
|
|
||||||
stroke-dasharray : SCALE_RATIO * 1, SCALE_RATIO * 200
|
|
||||||
stroke-dashoffset : SCALE_RATIO * 0
|
|
||||||
50%
|
|
||||||
stroke-dasharray : SCALE_RATIO * 89, SCALE_RATIO * 200
|
|
||||||
stroke-dashoffset : SCALE_RATIO * -35
|
|
||||||
100%
|
|
||||||
stroke-dasharray : SCALE_RATIO * 89, SCALE_RATIO * 200
|
|
||||||
stroke-dashoffset : SCALE_RATIO * -124
|
|
||||||
|
|
||||||
@keyframes colors
|
|
||||||
0%
|
|
||||||
stroke: #4285F4
|
|
||||||
25%
|
|
||||||
stroke: #DE3E35
|
|
||||||
50%
|
|
||||||
stroke: #F7C223
|
|
||||||
75%
|
|
||||||
stroke: #1B9A59
|
|
||||||
100%
|
|
||||||
stroke: #4285F4
|
|
|
@ -0,0 +1,81 @@
|
||||||
|
import React from 'react';
|
||||||
|
import PureRenderMixin from 'react-addons-pure-render-mixin';
|
||||||
|
import Ripple from '../ripple';
|
||||||
|
import style from './style';
|
||||||
|
import events from '../utils/events';
|
||||||
|
|
||||||
|
export default React.createClass({
|
||||||
|
mixins: [PureRenderMixin],
|
||||||
|
|
||||||
|
displayName: 'RadioButton',
|
||||||
|
|
||||||
|
propTypes: {
|
||||||
|
checked: React.PropTypes.bool,
|
||||||
|
className: React.PropTypes.string,
|
||||||
|
disabled: React.PropTypes.bool,
|
||||||
|
label: React.PropTypes.string,
|
||||||
|
name: React.PropTypes.string,
|
||||||
|
onBlur: React.PropTypes.func,
|
||||||
|
onChange: React.PropTypes.func,
|
||||||
|
onFocus: React.PropTypes.func,
|
||||||
|
value: React.PropTypes.any
|
||||||
|
},
|
||||||
|
|
||||||
|
getDefaultProps () {
|
||||||
|
return {
|
||||||
|
checked: false,
|
||||||
|
className: '',
|
||||||
|
disabled: false
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
handleClick (event) {
|
||||||
|
events.pauseEvent(event);
|
||||||
|
if (!this.props.disabled) this.handleChange(event);
|
||||||
|
},
|
||||||
|
|
||||||
|
handleChange (event) {
|
||||||
|
if (!this.props.checked && this.props.onChange) {
|
||||||
|
this.props.onChange(event, this);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
handleMouseDown (event) {
|
||||||
|
if (!this.props.disabled) this.refs.ripple.start(event);
|
||||||
|
},
|
||||||
|
|
||||||
|
handleInputClick (event) {
|
||||||
|
events.pauseEvent(event);
|
||||||
|
},
|
||||||
|
|
||||||
|
render () {
|
||||||
|
let labelClassName = style[this.props.disabled ? 'disabled' : 'field'];
|
||||||
|
let radioClassName = style[this.props.checked ? 'radio-checked' : 'radio'];
|
||||||
|
if (this.props.className) labelClassName += ` ${this.props.className}`;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<label className={labelClassName} onClick={this.handleClick}>
|
||||||
|
<input
|
||||||
|
{...this.props}
|
||||||
|
ref='input'
|
||||||
|
type='radio'
|
||||||
|
className={style.input}
|
||||||
|
onChange={this.handleChange}
|
||||||
|
onClick={this.handleInputClick}
|
||||||
|
/>
|
||||||
|
<span role='radio' className={radioClassName} onMouseDown={this.handleMouseDown}>
|
||||||
|
<Ripple ref='ripple' role='ripple' className={style.ripple} spread={3} centered />
|
||||||
|
</span>
|
||||||
|
{ this.props.label ? <span className={style.text}>{this.props.label}</span> : null }
|
||||||
|
</label>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
blur () {
|
||||||
|
this.refs.input.blur();
|
||||||
|
},
|
||||||
|
|
||||||
|
focus () {
|
||||||
|
this.refs.input.focus();
|
||||||
|
}
|
||||||
|
});
|
|
@ -0,0 +1,112 @@
|
||||||
|
@import "../variables";
|
||||||
|
@import "../mixins";
|
||||||
|
|
||||||
|
$radio-button-size: 1.6 * $unit !default;
|
||||||
|
$radio-inner-margin: $radio-button-size / 4;
|
||||||
|
$radio-inner-color: unquote("rgb(#{$color-primary})") !default;
|
||||||
|
$radio-focus-color: unquote("rgba(#{$color-black}, 0.1)") !default;
|
||||||
|
$radio-checked-focus-color: unquote("rgba(#{$color-primary}, 0.26)") !default;
|
||||||
|
$radio-text-color: unquote("rgb(#{$color-black})") !default;
|
||||||
|
$radio-disabled-color: unquote("rgba(#{$color-black}, 0.26)") !default;
|
||||||
|
|
||||||
|
.field {
|
||||||
|
position: relative;
|
||||||
|
display: block;
|
||||||
|
height: $radio-button-size;
|
||||||
|
margin-bottom: 1.5 * $unit;
|
||||||
|
white-space: nowrap;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text {
|
||||||
|
display: inline-block;
|
||||||
|
padding-left: $unit;
|
||||||
|
font-size: 1.4 * $unit;
|
||||||
|
line-height: $radio-button-size;
|
||||||
|
color: $radio-text-color;
|
||||||
|
white-space: nowrap;
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input {
|
||||||
|
position: absolute;
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
border: 0;
|
||||||
|
opacity: 0;
|
||||||
|
appearance: none;
|
||||||
|
|
||||||
|
&:focus:not(&:active) {
|
||||||
|
+ .radio {
|
||||||
|
box-shadow: 0 0 0 $unit $radio-focus-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ .radio-checked {
|
||||||
|
box-shadow: 0 0 0 $unit $radio-checked-focus-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.radio {
|
||||||
|
position: relative;
|
||||||
|
display: inline-block;
|
||||||
|
width: $radio-button-size;
|
||||||
|
height: $radio-button-size;
|
||||||
|
vertical-align: top;
|
||||||
|
cursor: pointer;
|
||||||
|
border: .2 * $unit solid $radio-text-color;
|
||||||
|
border-radius: 50%;
|
||||||
|
|
||||||
|
&:before {
|
||||||
|
@include material-animation-default();
|
||||||
|
position: absolute;
|
||||||
|
top: $radio-inner-margin - .2 * $unit;
|
||||||
|
left: $radio-inner-margin - .2 * $unit;
|
||||||
|
width: $radio-button-size - $radio-inner-margin * 2;
|
||||||
|
height: $radio-button-size - $radio-inner-margin * 2;
|
||||||
|
content: "";
|
||||||
|
background-color: $radio-inner-color;
|
||||||
|
border-radius: 50%;
|
||||||
|
transition-property: transform;
|
||||||
|
transform: scale3d(0, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.radio-checked {
|
||||||
|
@extend .radio;
|
||||||
|
border: .2 * $unit solid $radio-inner-color;
|
||||||
|
|
||||||
|
&:before {
|
||||||
|
transform: scale3d(1, 1, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ripple {
|
||||||
|
background-color: $radio-inner-color;
|
||||||
|
opacity: .3;
|
||||||
|
transition-duration: 650ms;
|
||||||
|
}
|
||||||
|
|
||||||
|
.disabled {
|
||||||
|
@extend .field;
|
||||||
|
|
||||||
|
.text {
|
||||||
|
color: $radio-disabled-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
.radio {
|
||||||
|
cursor: auto;
|
||||||
|
border-color: $radio-disabled-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
.radio-checked {
|
||||||
|
cursor: auto;
|
||||||
|
border-color: $radio-disabled-color;
|
||||||
|
|
||||||
|
&:before {
|
||||||
|
background-color: $radio-disabled-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,66 @@
|
||||||
|
import React from 'react';
|
||||||
|
import PureRenderMixin from 'react-addons-pure-render-mixin';
|
||||||
|
import RadioButton from '../radio_button';
|
||||||
|
|
||||||
|
export default React.createClass({
|
||||||
|
mixins: [PureRenderMixin],
|
||||||
|
|
||||||
|
displayName: 'RadioGroup',
|
||||||
|
|
||||||
|
propTypes: {
|
||||||
|
className: React.PropTypes.string,
|
||||||
|
disabled: React.PropTypes.bool,
|
||||||
|
name: React.PropTypes.string,
|
||||||
|
onChange: React.PropTypes.func,
|
||||||
|
value: React.PropTypes.any
|
||||||
|
},
|
||||||
|
|
||||||
|
getDefaultProps () {
|
||||||
|
return {
|
||||||
|
className: '',
|
||||||
|
disabled: false
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
getInitialState () {
|
||||||
|
return { value: this.props.value };
|
||||||
|
},
|
||||||
|
|
||||||
|
handleChange (value, event) {
|
||||||
|
this.setState({value: value}, () => {
|
||||||
|
if (this.props.onChange) this.props.onChange(event, this);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
renderRadioButtons () {
|
||||||
|
return React.Children.map(this.props.children, (radio, idx) => {
|
||||||
|
return (
|
||||||
|
<RadioButton
|
||||||
|
{...radio.props}
|
||||||
|
checked={radio.props.value === this.state.value}
|
||||||
|
disabled={this.props.disabled || radio.props.disabled}
|
||||||
|
key={idx}
|
||||||
|
label={radio.props.label}
|
||||||
|
onChange={this.handleChange.bind(this, radio.props.value)}
|
||||||
|
value={radio.props.value}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
render () {
|
||||||
|
return (
|
||||||
|
<div className={this.props.className}>
|
||||||
|
{this.renderRadioButtons()}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
getValue () {
|
||||||
|
return this.state.value;
|
||||||
|
},
|
||||||
|
|
||||||
|
setValue (value) {
|
||||||
|
this.setState({value: value});
|
||||||
|
}
|
||||||
|
});
|
|
@ -1,24 +1,26 @@
|
||||||
/* global React */
|
import React from 'react';
|
||||||
|
import ReactDOM from 'react-dom';
|
||||||
import { addons } from 'react/addons';
|
import PureRenderMixin from 'react-addons-pure-render-mixin';
|
||||||
import style from './style';
|
import style from './style.scss';
|
||||||
|
|
||||||
export default React.createClass({
|
export default React.createClass({
|
||||||
mixins: [addons.PureRenderMixin],
|
mixins: [PureRenderMixin],
|
||||||
|
|
||||||
displayName: 'Ripple',
|
displayName: 'Ripple',
|
||||||
|
|
||||||
propTypes: {
|
propTypes: {
|
||||||
auto: React.PropTypes.bool,
|
centered: React.PropTypes.bool,
|
||||||
className: React.PropTypes.string,
|
className: React.PropTypes.string,
|
||||||
loading: React.PropTypes.bool
|
loading: React.PropTypes.bool,
|
||||||
|
spread: React.PropTypes.number
|
||||||
},
|
},
|
||||||
|
|
||||||
getDefaultProps () {
|
getDefaultProps () {
|
||||||
return {
|
return {
|
||||||
auto: true,
|
centered: false,
|
||||||
className: '',
|
className: '',
|
||||||
loading: false
|
loading: false,
|
||||||
|
spread: 2
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -33,44 +35,39 @@ export default React.createClass({
|
||||||
},
|
},
|
||||||
|
|
||||||
start ({ pageX, pageY }) {
|
start ({ pageX, pageY }) {
|
||||||
|
document.addEventListener('mouseup', this.end);
|
||||||
const {top, left, width} = this._getDescriptor(pageX, pageY);
|
const {top, left, width} = this._getDescriptor(pageX, pageY);
|
||||||
this.setState({active: false, restarting: true, width: 0}, () => {
|
this.setState({active: false, restarting: true, width: 0}, () => {
|
||||||
this.refs.ripple.getDOMNode().offsetWidth; //eslint-disable-line no-unused-expressions
|
this.refs.ripple.offsetWidth; //eslint-disable-line no-unused-expressions
|
||||||
this.setState({active: true, restarting: false, top: top, left: left, width: width});
|
this.setState({active: true, restarting: false, top: top, left: left, width: width});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
end () {
|
end () {
|
||||||
|
document.removeEventListener('mouseup', this.end);
|
||||||
this.setState({active: false});
|
this.setState({active: false});
|
||||||
},
|
},
|
||||||
|
|
||||||
_getDescriptor (pageX, pageY) {
|
_getDescriptor (pageX, pageY) {
|
||||||
let { left, top, width } = this.getDOMNode().getBoundingClientRect();
|
let { left, top, height, width } = ReactDOM.findDOMNode(this).getBoundingClientRect();
|
||||||
return {
|
return {
|
||||||
left: pageX - left,
|
left: this.props.centered ? width / 2 : pageX - left,
|
||||||
top: pageY - top,
|
top: this.props.centered ? height / 2 : pageY - top,
|
||||||
width: width * 2.5
|
width: width * this.props.spread
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
let { left, top, width } = this.state;
|
let { left, top, width } = this.state;
|
||||||
let className = `${style.ripple} ${this.props.className}`;
|
let rippleStyle = {left: left, top: top, width: width, height: width};
|
||||||
if (this.state.active) className += ' active';
|
let className = style[this.props.loading ? 'loading' : 'normal'];
|
||||||
if (this.state.restarting) className += ' restarting';
|
if (this.state.active) className += ` ${style.active}`;
|
||||||
if (this.props.loading) className += ' loading';
|
if (this.state.restarting) className += ` ${style.restarting}`;
|
||||||
|
if (this.props.className) className += ` ${this.props.className}`;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<span
|
<span data-react-toolbox='ripple' className={style.wrapper}>
|
||||||
className={style.root}
|
<span ref="ripple" role='ripple' className={className} style={rippleStyle} />
|
||||||
onMouseDown={this.props.auto ? this.start : null}
|
|
||||||
onMouseUp={this.end}>
|
|
||||||
|
|
||||||
<span
|
|
||||||
ref="ripple"
|
|
||||||
className={className}
|
|
||||||
style={{left: left, top: top, width: width, height: width}}>
|
|
||||||
</span>
|
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
@import "../variables";
|
||||||
|
@import "../mixins";
|
||||||
|
|
||||||
|
$ripple-duration: 1.2s;
|
||||||
|
$ripple-final-opacity: .3;
|
||||||
|
$ripple-size: 15 * $unit;
|
||||||
|
|
||||||
|
%ripple {
|
||||||
|
position: absolute;
|
||||||
|
pointer-events: none;
|
||||||
|
background-color: currentColor;
|
||||||
|
border-radius: 50%;
|
||||||
|
transform: translate3d(-50%, -50%, 0);
|
||||||
|
transform-style: preserve-3d;
|
||||||
|
backface-visibility: hidden;
|
||||||
|
will-change: width, height, opacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wrapper {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.normal {
|
||||||
|
@extend %ripple;
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
opacity: $ripple-final-opacity;
|
||||||
|
transition-timing-function: $animation-curve-linear-out-slow-in;
|
||||||
|
transition-duration: $ripple-duration;
|
||||||
|
transition-property: height, width;
|
||||||
|
|
||||||
|
&:not(.active) {
|
||||||
|
opacity: 0;
|
||||||
|
transition-property: height, width, opacity;
|
||||||
|
|
||||||
|
&.restarting {
|
||||||
|
transition-property: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.loading {
|
||||||
|
@extend %ripple;
|
||||||
|
@include ripple-loading(ripple, $ripple-size, $ripple-size);
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
width: $ripple-size;
|
||||||
|
height: $ripple-size;
|
||||||
|
opacity: $ripple-final-opacity;
|
||||||
|
animation-name: ripple;
|
||||||
|
animation-duration: $ripple-duration;
|
||||||
|
animation-timing-function: $animation-curve-linear-out-slow-in;
|
||||||
|
animation-iteration-count: infinite;
|
||||||
|
}
|
|
@ -1,47 +0,0 @@
|
||||||
@import '../constants'
|
|
||||||
|
|
||||||
FINAL_OPACITY = .4
|
|
||||||
|
|
||||||
:local(.root)
|
|
||||||
position : absolute
|
|
||||||
top : 0
|
|
||||||
left : 0
|
|
||||||
right : 0
|
|
||||||
bottom : 0
|
|
||||||
|
|
||||||
:local(.ripple)
|
|
||||||
position : absolute
|
|
||||||
background-color : currentColor
|
|
||||||
transform : translateX(-50%) translateY(-50%)
|
|
||||||
border-radius : 50%
|
|
||||||
width : 0
|
|
||||||
height : 0
|
|
||||||
opacity : FINAL_OPACITY
|
|
||||||
transition-duration : 1.4 * ANIMATION_DURATION
|
|
||||||
transition-property : height, width
|
|
||||||
|
|
||||||
&:not(.active).restarting
|
|
||||||
transition-property : none
|
|
||||||
|
|
||||||
&:not(.active)
|
|
||||||
opacity : 0
|
|
||||||
transition-property : opacity, height, width
|
|
||||||
|
|
||||||
&.loading
|
|
||||||
animation-name : ripple
|
|
||||||
animation-iteration-count : infinite
|
|
||||||
animation-timing-function : ANIMATION_EASE
|
|
||||||
animation-duration : (2 * ANIMATION_DURATION)
|
|
||||||
height : (4 * UNIT)
|
|
||||||
width : (4 * UNIT)
|
|
||||||
left : 50%
|
|
||||||
opacity : 0
|
|
||||||
top : 50%
|
|
||||||
|
|
||||||
@keyframes ripple
|
|
||||||
0%
|
|
||||||
width : 0
|
|
||||||
height : 0
|
|
||||||
opacity : FINAL_OPACITY
|
|
||||||
100%
|
|
||||||
opacity : 0
|
|
|
@ -1,14 +1,13 @@
|
||||||
/* global React */
|
|
||||||
|
|
||||||
import expect from 'expect';
|
import expect from 'expect';
|
||||||
import sinon from 'sinon';
|
import sinon from 'sinon';
|
||||||
import utils from '../../utils/testing';
|
import utils from '../../utils/testing';
|
||||||
|
import style from '../../slider/style';
|
||||||
import ProgressBar from '../../progress_bar';
|
import ProgressBar from '../../progress_bar';
|
||||||
import Input from '../../input';
|
import Input from '../../input';
|
||||||
import Slider from '../index';
|
import Slider from '../index';
|
||||||
|
import TestUtils from 'react-addons-test-utils';
|
||||||
|
|
||||||
describe('Slider', function () {
|
describe('Slider', function () {
|
||||||
const TestUtils = React.addons.TestUtils;
|
|
||||||
let props, state, slider, progress, input;
|
let props, state, slider, progress, input;
|
||||||
|
|
||||||
describe('#positionToValue', function () {
|
describe('#positionToValue', function () {
|
||||||
|
@ -109,10 +108,10 @@ describe('Slider', function () {
|
||||||
|
|
||||||
it('contains the proper number of snaps when snapped', function () {
|
it('contains the proper number of snaps when snapped', function () {
|
||||||
slider = utils.shallowRenderComponent(Slider, {editable: true, pinned: true});
|
slider = utils.shallowRenderComponent(Slider, {editable: true, pinned: true});
|
||||||
expect(slider.props.className).toContain('ring');
|
expect(slider.props.className).toContain(style.ring);
|
||||||
expect(slider.props.className).toContain('pinned');
|
expect(slider.props.className).toContain(style.pinned);
|
||||||
slider = utils.shallowRenderComponent(Slider, {editable: true, value: 50});
|
slider = utils.shallowRenderComponent(Slider, {editable: true, value: 50});
|
||||||
expect(slider.props.className).toNotContain('ring');
|
expect(slider.props.className).toNotContain(style.ring);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* global React */
|
import React from 'react';
|
||||||
|
import ReactDOM from 'react-dom';
|
||||||
import css from './style';
|
import style from './style';
|
||||||
import utils from '../utils';
|
import utils from '../utils';
|
||||||
import ProgressBar from '../progress_bar';
|
import ProgressBar from '../progress_bar';
|
||||||
import Input from '../input';
|
import Input from '../input';
|
||||||
|
@ -58,7 +58,7 @@ export default React.createClass({
|
||||||
},
|
},
|
||||||
|
|
||||||
onResize () {
|
onResize () {
|
||||||
const {left, right} = this.refs.progressbar.getDOMNode().getBoundingClientRect();
|
const {left, right} = ReactDOM.findDOMNode(this.refs.progressbar).getBoundingClientRect();
|
||||||
this.setState({sliderStart: left, sliderLength: right - left});
|
this.setState({sliderStart: left, sliderLength: right - left});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -70,15 +70,15 @@ export default React.createClass({
|
||||||
utils.events.removeEventsFromDocument(this.getKeyboardEvents());
|
utils.events.removeEventsFromDocument(this.getKeyboardEvents());
|
||||||
},
|
},
|
||||||
|
|
||||||
onInputChange (event) {
|
onInputChange () {
|
||||||
this.setState({value: this.trimValue(event.target.value) });
|
this.setState({value: this.trimValue(this.refs.input.getValue()) });
|
||||||
},
|
},
|
||||||
|
|
||||||
onKeyDown (event) {
|
onKeyDown (event) {
|
||||||
event.stopPropagation();
|
if ([13, 27].indexOf(event.keyCode) !== -1) ReactDOM.findDOMNode(this).blur();
|
||||||
if (event.keyCode in [13, 27]) this.getDOMNode().blur();
|
|
||||||
if (event.keyCode === 38) this.addToValue(this.props.step);
|
if (event.keyCode === 38) this.addToValue(this.props.step);
|
||||||
if (event.keyCode === 40) this.addToValue(-this.props.step);
|
if (event.keyCode === 40) this.addToValue(-this.props.step);
|
||||||
|
if (event.keyCode !== 9) utils.events.pauseEvent(event);
|
||||||
},
|
},
|
||||||
|
|
||||||
onMouseDown (event) {
|
onMouseDown (event) {
|
||||||
|
@ -176,10 +176,10 @@ export default React.createClass({
|
||||||
renderSnaps () {
|
renderSnaps () {
|
||||||
if (this.props.snaps) {
|
if (this.props.snaps) {
|
||||||
return (
|
return (
|
||||||
<div ref='snaps' className={css.snaps}>
|
<div ref='snaps' className={style.snaps}>
|
||||||
{
|
{
|
||||||
utils.range(0, (this.props.max - this.props.min) / this.props.step).map(i => {
|
utils.range(0, (this.props.max - this.props.min) / this.props.step).map(i => {
|
||||||
return (<div key={`span-${i}`} className={css.snap}></div>);
|
return (<div key={`span-${i}`} className={style.snap}></div>);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
@ -192,7 +192,7 @@ export default React.createClass({
|
||||||
return (
|
return (
|
||||||
<Input
|
<Input
|
||||||
ref='input'
|
ref='input'
|
||||||
className={css.input}
|
className={style.input}
|
||||||
onChange={this.onInputChange}
|
onChange={this.onInputChange}
|
||||||
value={this.valueForInput(this.state.value)} />
|
value={this.valueForInput(this.state.value)} />
|
||||||
);
|
);
|
||||||
|
@ -202,38 +202,39 @@ export default React.createClass({
|
||||||
render () {
|
render () {
|
||||||
let knobStyles = utils.prefixer({transform: `translateX(${this.knobOffset()}px)`});
|
let knobStyles = utils.prefixer({transform: `translateX(${this.knobOffset()}px)`});
|
||||||
let className = this.props.className;
|
let className = this.props.className;
|
||||||
if (this.props.editable) className += ' editable';
|
if (this.props.editable) className += ` ${style.editable}`;
|
||||||
if (this.props.pinned) className += ' pinned';
|
if (this.props.pinned) className += ` ${style.pinned}`;
|
||||||
if (this.state.pressed) className += ' pressed';
|
if (this.state.pressed) className += ` ${style.pressed}`;
|
||||||
if (this.state.value === this.props.min) className += ' ring';
|
if (this.state.value === this.props.min) className += ` ${style.ring}`;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={css.root + className}
|
data-react-toolbox='slider'
|
||||||
|
className={style.root + className}
|
||||||
tabIndex='0'
|
tabIndex='0'
|
||||||
onFocus={this.onSliderFocus}
|
onFocus={this.onSliderFocus}
|
||||||
onBlur={this.onSliderBlur} >
|
onBlur={this.onSliderBlur} >
|
||||||
|
|
||||||
<div
|
<div
|
||||||
ref='slider'
|
ref='slider'
|
||||||
className={css.container}
|
className={style.container}
|
||||||
onTouchStart={this.onTouchStart}
|
onTouchStart={this.onTouchStart}
|
||||||
onMouseDown={this.onMouseDown} >
|
onMouseDown={this.onMouseDown} >
|
||||||
|
|
||||||
<div
|
<div
|
||||||
ref='knob'
|
ref='knob'
|
||||||
className={css.knob}
|
className={style.knob}
|
||||||
style={knobStyles}
|
style={knobStyles}
|
||||||
onMouseDown={this.onMouseDown}
|
onMouseDown={this.onMouseDown}
|
||||||
onTouchStart={this.onTouchStart} >
|
onTouchStart={this.onTouchStart} >
|
||||||
<div className={css.knobInner} data-value={parseInt(this.state.value)}></div>
|
<div className={style.innerknob} data-value={parseInt(this.state.value)}></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={css.progress}>
|
<div className={style.progress}>
|
||||||
<ProgressBar
|
<ProgressBar
|
||||||
ref='progressbar'
|
ref='progressbar'
|
||||||
mode='determinate'
|
mode='determinate'
|
||||||
className={css.progressInner}
|
className={style.innerprogress}
|
||||||
value={this.state.value}
|
value={this.state.value}
|
||||||
max={this.props.max}
|
max={this.props.max}
|
||||||
min={this.props.min}/>
|
min={this.props.min}/>
|
||||||
|
|
|
@ -0,0 +1,220 @@
|
||||||
|
@import "../variables";
|
||||||
|
|
||||||
|
$slider-main-color: unquote("rgb(#{$color-primary})") !default;
|
||||||
|
$slider-main-color-contrast: unquote("rgb(#{$color-primary-contrast})") !default;
|
||||||
|
$slider-snap-color: unquote("rgb(#{$color-black})") !default;
|
||||||
|
$slider-knob-size: 3.2 * $unit;
|
||||||
|
$slider-inner-knob-size: 1.2 * $unit;
|
||||||
|
$slider-snap-size: .2 * $unit;
|
||||||
|
$slider-input-width: 5 * $unit;
|
||||||
|
$slider-bar-height: .2 * $unit;
|
||||||
|
$slider-pin-size: 2.6 * $unit;
|
||||||
|
$slider-pin-elevation: 1.7 * $unit;
|
||||||
|
$slider-side-separation: 1 * $unit;
|
||||||
|
$slider-empty-knob-border: .2 * $unit;
|
||||||
|
|
||||||
|
.container {
|
||||||
|
position: relative;
|
||||||
|
width: calc(100% - #{$slider-knob-size});
|
||||||
|
height: $slider-knob-size;
|
||||||
|
margin-right: $slider-knob-size;
|
||||||
|
user-select: none;
|
||||||
|
|
||||||
|
&:not(:last-child) {
|
||||||
|
margin-right: $slider-side-separation + $slider-knob-size;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:not(:first-child) {
|
||||||
|
margin-left: $slider-side-separation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.knob {
|
||||||
|
position: relative;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
z-index: $z-index-higher;
|
||||||
|
display: flex;
|
||||||
|
width: $slider-knob-size;
|
||||||
|
height: $slider-knob-size;
|
||||||
|
flex-direction: row;
|
||||||
|
background-color: transparent;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.innerknob {
|
||||||
|
z-index: $z-index-high;
|
||||||
|
width: $slider-inner-knob-size;
|
||||||
|
height: $slider-inner-knob-size;
|
||||||
|
background-color: $slider-main-color;
|
||||||
|
border-radius: 50%;
|
||||||
|
transition-timing-function: $animation-curve-default;
|
||||||
|
transition-duration: .1s;
|
||||||
|
transition-property: height, width, background-color, border;
|
||||||
|
}
|
||||||
|
|
||||||
|
.snaps {
|
||||||
|
position: absolute;
|
||||||
|
top: $slider-knob-size / 2 - $slider-snap-size / 2;
|
||||||
|
left: 0;
|
||||||
|
display: flex;
|
||||||
|
width: calc(100% + #{$slider-snap-size});
|
||||||
|
height: $slider-snap-size;
|
||||||
|
flex-direction: row;
|
||||||
|
pointer-events: none;
|
||||||
|
|
||||||
|
&:after {
|
||||||
|
display: block;
|
||||||
|
width: $slider-snap-size;
|
||||||
|
height: $slider-snap-size;
|
||||||
|
content: "";
|
||||||
|
background-color: $slider-snap-color;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.snap {
|
||||||
|
flex: 1;
|
||||||
|
|
||||||
|
&:after {
|
||||||
|
display: block;
|
||||||
|
width: $slider-snap-size;
|
||||||
|
height: $slider-snap-size;
|
||||||
|
content: "";
|
||||||
|
background-color: $slider-snap-color;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.input {
|
||||||
|
width: $slider-input-width;
|
||||||
|
padding: 0;
|
||||||
|
margin-bottom: 0;
|
||||||
|
|
||||||
|
> input {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: $slider-knob-size / 2;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
.innerprogress {
|
||||||
|
position: absolute;
|
||||||
|
top: $slider-knob-size / 2 - $slider-bar-height / 2;
|
||||||
|
height: $slider-bar-height;
|
||||||
|
|
||||||
|
[data-ref="value"] {
|
||||||
|
transition-duration: 0s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.root:focus .knob:before {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
z-index: $z-index-normal;
|
||||||
|
content: "";
|
||||||
|
background-color: $slider-main-color;
|
||||||
|
border-radius: 50%;
|
||||||
|
opacity: .26;
|
||||||
|
}
|
||||||
|
|
||||||
|
.root.editable {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
:local(.root).pinned :local(.innerknob) {
|
||||||
|
&:before {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: $slider-pin-size;
|
||||||
|
height: $slider-pin-size;
|
||||||
|
margin-left: ($slider-knob-size - $slider-pin-size) / 2;
|
||||||
|
content: "";
|
||||||
|
background-color: $slider-main-color;
|
||||||
|
border-radius: 50% 50% 50% 0;
|
||||||
|
transition: transform .2s ease, background-color .18s ease;
|
||||||
|
transform: rotate(-45deg) scale(0) translate(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:after {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: $slider-knob-size;
|
||||||
|
height: $slider-pin-size;
|
||||||
|
font-size: 10px;
|
||||||
|
color: $color-background;
|
||||||
|
text-align: center;
|
||||||
|
content: attr(data-value);
|
||||||
|
transition: transform .2s ease, background-color .18s ease;
|
||||||
|
transform: scale(0) translate(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.root.pressed {
|
||||||
|
&.pinned .innerknob {
|
||||||
|
&:before {
|
||||||
|
transition-delay: 100ms;
|
||||||
|
transform: rotate(-45deg) scale(1) translate($slider-pin-elevation, - $slider-pin-elevation);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:after {
|
||||||
|
transition-delay: 100ms;
|
||||||
|
transform: scale(1) translate(0, - $slider-pin-elevation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:not(.pinned) {
|
||||||
|
&.ring .progress {
|
||||||
|
left: $slider-knob-size / 2 + ($slider-knob-size - $slider-empty-knob-border * 2) / 2;
|
||||||
|
width: calc(100% - #{($slider-knob-size - $slider-empty-knob-border * 2) / 2});
|
||||||
|
}
|
||||||
|
|
||||||
|
.innerknob {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
transform: translateZ(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.root.ring {
|
||||||
|
.innerknob {
|
||||||
|
background-color: transparent;
|
||||||
|
border: $slider-empty-knob-border solid $color-divider;
|
||||||
|
|
||||||
|
&:before {
|
||||||
|
background-color: $slider-main-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress {
|
||||||
|
left: $slider-knob-size / 2 + $slider-empty-knob-border * 2;
|
||||||
|
width: calc(100% - #{$slider-empty-knob-border * 2});
|
||||||
|
transition: left 0.18s ease, width 0.18s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.pinned {
|
||||||
|
.innerknob {
|
||||||
|
background-color: $color-background;
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress {
|
||||||
|
left: $slider-knob-size / 2;
|
||||||
|
width: calc(100%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,163 +0,0 @@
|
||||||
@import '../constants'
|
|
||||||
|
|
||||||
RANGE_SIDE_SEPARATION = 20px
|
|
||||||
|
|
||||||
:local(.container)
|
|
||||||
height : 32px
|
|
||||||
margin-right : 32px
|
|
||||||
position : relative
|
|
||||||
user-select : none
|
|
||||||
width : calc(100% - 32px)
|
|
||||||
&:not(:last-child)
|
|
||||||
margin-right : RANGE_SIDE_SEPARATION + 32px
|
|
||||||
&:not(:first-child)
|
|
||||||
margin-left : RANGE_SIDE_SEPARATION
|
|
||||||
|
|
||||||
:local(.knob)
|
|
||||||
align-items : center
|
|
||||||
background-color : transparent
|
|
||||||
display : flex
|
|
||||||
flex-direction : row
|
|
||||||
height : 32px
|
|
||||||
justify-content : center
|
|
||||||
left : 0
|
|
||||||
position : relative
|
|
||||||
top : 0
|
|
||||||
width : 32px
|
|
||||||
z-index : 5
|
|
||||||
|
|
||||||
:local(.knobInner)
|
|
||||||
background-color : ACCENT
|
|
||||||
border-radius : 50%
|
|
||||||
height : 12px
|
|
||||||
transition-duration : 0.1s
|
|
||||||
transition-property : height, width, background-color, border
|
|
||||||
transition-timing-function : ease
|
|
||||||
width : 12px
|
|
||||||
z-index : 4
|
|
||||||
|
|
||||||
:local(.snaps)
|
|
||||||
display : flex
|
|
||||||
flex-direction : row
|
|
||||||
height : 2px
|
|
||||||
left : 0
|
|
||||||
pointer-events : none
|
|
||||||
position : absolute
|
|
||||||
top : 15px
|
|
||||||
width : calc(100% + 2px)
|
|
||||||
&:after
|
|
||||||
background-color : black
|
|
||||||
border-radius : 50%
|
|
||||||
content : ""
|
|
||||||
display : block
|
|
||||||
height : 2px
|
|
||||||
width : 2px
|
|
||||||
|
|
||||||
:local(.snap)
|
|
||||||
flex : 1
|
|
||||||
&:after
|
|
||||||
background-color : black
|
|
||||||
border-radius : 50%
|
|
||||||
content : ""
|
|
||||||
display : block
|
|
||||||
height : 2px
|
|
||||||
width : 2px
|
|
||||||
|
|
||||||
:local(.input)
|
|
||||||
margin-bottom : 0
|
|
||||||
text-align : center
|
|
||||||
width : 40px
|
|
||||||
|
|
||||||
:local(.progress)
|
|
||||||
height : 100%
|
|
||||||
left : 16px
|
|
||||||
position : absolute
|
|
||||||
top : 0
|
|
||||||
width : 100%
|
|
||||||
|
|
||||||
:local(.progressInner)
|
|
||||||
height : 2px
|
|
||||||
position : absolute
|
|
||||||
top : 15px
|
|
||||||
|
|
||||||
[data-ref="value"]
|
|
||||||
transition-duration : 0s
|
|
||||||
|
|
||||||
// When its focused
|
|
||||||
:local(.root):focus :local(.knob):before
|
|
||||||
background-color : ACCENT
|
|
||||||
border-radius : 50%
|
|
||||||
bottom : 0
|
|
||||||
content : ""
|
|
||||||
left : 0
|
|
||||||
position : absolute
|
|
||||||
right : 0
|
|
||||||
top : 0
|
|
||||||
opacity : .26
|
|
||||||
z-index : 2
|
|
||||||
|
|
||||||
:local(.root).editable
|
|
||||||
display : flex
|
|
||||||
align-items : center
|
|
||||||
flex-direction : row
|
|
||||||
|
|
||||||
// When its pinned
|
|
||||||
:local(.root).pinned :local(.knobInner)
|
|
||||||
&:before
|
|
||||||
content : ""
|
|
||||||
position : absolute
|
|
||||||
top : 0
|
|
||||||
background-color : ACCENT
|
|
||||||
left : 0
|
|
||||||
width : 26px
|
|
||||||
height : 26px
|
|
||||||
margin-left : 3px
|
|
||||||
border-radius : 50% 50% 50% 0
|
|
||||||
transition-delay : 1s
|
|
||||||
transform : rotate(-45deg) scale(0) translate(0)
|
|
||||||
transition : transform .2s ease, background-color .18s ease
|
|
||||||
|
|
||||||
&:after
|
|
||||||
color : white
|
|
||||||
content : attr(data-value)
|
|
||||||
font-size : 10px
|
|
||||||
height : 26px
|
|
||||||
left : 0
|
|
||||||
position : absolute
|
|
||||||
text-align : center
|
|
||||||
top : 0
|
|
||||||
transform : scale(0) translate(0)
|
|
||||||
transition : transform .2s ease, background-color .18s ease
|
|
||||||
width : 32px
|
|
||||||
|
|
||||||
// When the knob is pressed
|
|
||||||
:local(.root).pressed.pinned :local(.knobInner)
|
|
||||||
&:before
|
|
||||||
transition-delay : 100ms
|
|
||||||
transform : rotate(-45deg) scale(1) translate(17px, -17px)
|
|
||||||
|
|
||||||
&:after
|
|
||||||
transition-delay : 100ms
|
|
||||||
transform : scale(1) translate(0, -17px)
|
|
||||||
|
|
||||||
:local(.root).pressed:not(.pinned) :local(.knobInner)
|
|
||||||
height : 100%
|
|
||||||
transform : translateZ(0)
|
|
||||||
width : 100%
|
|
||||||
|
|
||||||
:local(.root).pressed:not(.pinned).ring :local(.progress)
|
|
||||||
left : 30px
|
|
||||||
width : calc(100% - 14px)
|
|
||||||
|
|
||||||
// When there is no current value
|
|
||||||
:local(.root).ring :local(.knobInner)
|
|
||||||
background-color : transparent
|
|
||||||
border : 2px solid #c8c8c8
|
|
||||||
|
|
||||||
:local(.root).ring :local(.knobInner):before
|
|
||||||
background-color : #c8c8c8
|
|
||||||
|
|
||||||
:local(.root).ring :local(.progress)
|
|
||||||
left : 20px
|
|
||||||
transition : left 0.18s ease, width 0.18s ease
|
|
||||||
width : calc(100% - 4px)
|
|
|
@ -1,70 +1,99 @@
|
||||||
/* global React */
|
import React from 'react';
|
||||||
|
import PureRenderMixin from 'react-addons-pure-render-mixin';
|
||||||
import { addons } from 'react/addons';
|
import Ripple from '../ripple';
|
||||||
import style from './style';
|
import style from './style';
|
||||||
|
import events from '../utils/events';
|
||||||
|
|
||||||
export default React.createClass({
|
export default React.createClass({
|
||||||
mixins: [addons.PureRenderMixin],
|
mixins: [PureRenderMixin],
|
||||||
|
|
||||||
displayName: 'Switch',
|
displayName: 'Switch',
|
||||||
|
|
||||||
propTypes: {
|
propTypes: {
|
||||||
|
checked: React.PropTypes.bool,
|
||||||
className: React.PropTypes.string,
|
className: React.PropTypes.string,
|
||||||
disabled: React.PropTypes.bool,
|
disabled: React.PropTypes.bool,
|
||||||
label: React.PropTypes.string,
|
label: React.PropTypes.string,
|
||||||
|
name: React.PropTypes.string,
|
||||||
|
onBlur: React.PropTypes.func,
|
||||||
onChange: React.PropTypes.func,
|
onChange: React.PropTypes.func,
|
||||||
value: React.PropTypes.bool
|
onFocus: React.PropTypes.func
|
||||||
},
|
},
|
||||||
|
|
||||||
getDefaultProps () {
|
getDefaultProps () {
|
||||||
return {
|
return {
|
||||||
className: ''
|
checked: false,
|
||||||
|
className: '',
|
||||||
|
disabled: false
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
getInitialState () {
|
getInitialState () {
|
||||||
return {
|
return { checked: this.props.checked };
|
||||||
value: this.props.value
|
|
||||||
};
|
|
||||||
},
|
},
|
||||||
|
|
||||||
componentWillReceiveProps (next_props) {
|
handleChange (event) {
|
||||||
if (next_props.value) {
|
this.setState({checked: !this.state.checked}, () => {
|
||||||
this.setState({value: next_props.value});
|
if (this.props.onChange) this.props.onChange(event, this);
|
||||||
}
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
onClick (event) {
|
handleClick (event) {
|
||||||
if (!this.props.disabled) {
|
events.pauseEvent(event);
|
||||||
this.setState({value: !this.state.value});
|
if (!this.props.disabled) this.handleChange(event);
|
||||||
setTimeout(() => {
|
},
|
||||||
if (this.props.onChange) this.props.onChange(event, this);
|
|
||||||
}, 10);
|
handleInputClick (event) {
|
||||||
}
|
events.pauseEvent(event);
|
||||||
|
},
|
||||||
|
|
||||||
|
handleMouseDown (event) {
|
||||||
|
if (!this.props.disabled) this.refs.ripple.start(event);
|
||||||
},
|
},
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
let className = `${style.root} ${this.props.className}`;
|
let labelClassName = style[this.props.disabled ? 'disabled' : 'field'];
|
||||||
if (this.state.value) className += ' checked';
|
let switchClassName = style[this.state.checked ? 'switch-on' : 'switch-off'];
|
||||||
if (this.props.disabled) className += ' disabled';
|
if (this.props.className) labelClassName += ` ${this.props.className}`;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<label
|
||||||
data-react-toolbox='switch'
|
data-react-toolbox='checkbox'
|
||||||
className={className}
|
className={labelClassName}
|
||||||
onClick={this.onClick}
|
onClick={this.handleClick}
|
||||||
>
|
>
|
||||||
<span></span>
|
<input
|
||||||
{ this.props.label ? <label>{this.props.label}</label> : null }
|
{...this.props}
|
||||||
</div>
|
ref='input'
|
||||||
|
type='checkbox'
|
||||||
|
checked={this.state.checked}
|
||||||
|
className={style.input}
|
||||||
|
onChange={this.handleChange}
|
||||||
|
onClick={this.handleInputClick}
|
||||||
|
/>
|
||||||
|
<span role='switch' className={switchClassName}>
|
||||||
|
<span role='thumb' className={style.thumb} onMouseDown={this.handleMouseDown}>
|
||||||
|
<Ripple ref='ripple' role='ripple' className={style.ripple} spread={2.4} centered />
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
{ this.props.label ? <span className={style.text}>{this.props.label}</span> : null }
|
||||||
|
</label>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
getValue () {
|
blur () {
|
||||||
return this.state.value;
|
this.refs.input.blur();
|
||||||
},
|
},
|
||||||
|
|
||||||
setValue (data) {
|
focus () {
|
||||||
this.setState({value: data});
|
this.refs.input.focus();
|
||||||
|
},
|
||||||
|
|
||||||
|
getValue () {
|
||||||
|
return this.state.checked;
|
||||||
|
},
|
||||||
|
|
||||||
|
setValue (value) {
|
||||||
|
this.setState({checked: value});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,150 @@
|
||||||
|
@import "../variables";
|
||||||
|
@import "../mixins";
|
||||||
|
|
||||||
|
$switch-color: unquote("rgb(#{$color-primary})") !default;
|
||||||
|
$switch-text-color: unquote("rgb(#{$color-black})") !default;
|
||||||
|
$switch-thumb-off-color: unquote("rgb(#{$palette-grey-50})") !default;
|
||||||
|
$switch-track-on-color: unquote("rgba(#{$color-primary}, 0.5)") !default;
|
||||||
|
$switch-track-off-color: unquote("rgba(#{$color-black}, 0.26)") !default;
|
||||||
|
$switch-off-ripple-color: unquote("rgba(#{$color-black}, 0.4)") !default;
|
||||||
|
$switch-on-focus-color: unquote("rgba(#{$color-primary}, 0.26)") !default;
|
||||||
|
$switch-off-focus-color: unquote("rgba(#{$color-black}, 0.1)") !default;
|
||||||
|
$switch-disabled-thumb-color: unquote("rgb(#{$palette-grey-400})") !default;
|
||||||
|
$switch-disabled-track-color: unquote("rgba(#{$color-black}, 0.12)") !default;
|
||||||
|
$switch-disabled-text-color: unquote("rgba(#{$color-black}, 0.26)") !default;
|
||||||
|
|
||||||
|
$switch-total-height: 2.4 * $unit !default;
|
||||||
|
$switch-track-length: 3.6 * $unit !default;
|
||||||
|
$switch-track-height: 1.4 * $unit !default;
|
||||||
|
$switch-thumb-size: 2 * $unit !default;
|
||||||
|
$switch-thumb-on-color: $switch-color !default;
|
||||||
|
$switch-focus-init-size: .8 * $unit !default;
|
||||||
|
$switch-focus-size: $switch-total-height * 2 !default;
|
||||||
|
$switch-focus-diff: ($switch-focus-size - $switch-focus-init-size) / 2;
|
||||||
|
|
||||||
|
.field {
|
||||||
|
position: relative;
|
||||||
|
display: block;
|
||||||
|
height: $switch-total-height;
|
||||||
|
margin-bottom: 1.5 * $unit;
|
||||||
|
white-space: nowrap;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text {
|
||||||
|
display: inline-block;
|
||||||
|
padding-left: $unit;
|
||||||
|
font-size: 1.4 * $unit;
|
||||||
|
line-height: $switch-total-height;
|
||||||
|
color: $switch-text-color;
|
||||||
|
white-space: nowrap;
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
|
||||||
|
%switch {
|
||||||
|
position: relative;
|
||||||
|
display: inline-block;
|
||||||
|
width: $switch-track-length;
|
||||||
|
height: $switch-track-height;
|
||||||
|
margin-top: ($switch-total-height - $switch-track-height) / 2;
|
||||||
|
vertical-align: top;
|
||||||
|
cursor: pointer;
|
||||||
|
border-radius: $switch-track-height;
|
||||||
|
}
|
||||||
|
|
||||||
|
.thumb {
|
||||||
|
@include material-animation-default(.28s);
|
||||||
|
position: absolute;
|
||||||
|
top: ($switch-track-height - $switch-thumb-size) / 2;
|
||||||
|
width: $switch-thumb-size;
|
||||||
|
height: $switch-thumb-size;
|
||||||
|
cursor: pointer;
|
||||||
|
border-radius: 50%;
|
||||||
|
transition-property: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ripple {
|
||||||
|
background-color: $switch-color;
|
||||||
|
opacity: .3;
|
||||||
|
transition-duration: 650ms;
|
||||||
|
}
|
||||||
|
|
||||||
|
.switch-on {
|
||||||
|
@extend %switch;
|
||||||
|
background: $switch-track-on-color;
|
||||||
|
|
||||||
|
.thumb {
|
||||||
|
@include shadow-3dp();
|
||||||
|
left: $switch-track-length - $switch-thumb-size;
|
||||||
|
background: $switch-thumb-on-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.switch-off {
|
||||||
|
@extend %switch;
|
||||||
|
background: $switch-track-off-color;
|
||||||
|
|
||||||
|
.thumb {
|
||||||
|
@include shadow-2dp();
|
||||||
|
left: 0;
|
||||||
|
background: $switch-thumb-off-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ripple {
|
||||||
|
background: $switch-off-ripple-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
%thumb-focus {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
display: inline-block;
|
||||||
|
width: $switch-focus-init-size;
|
||||||
|
height: $switch-focus-init-size;
|
||||||
|
content: "";
|
||||||
|
background-color: transparent;
|
||||||
|
border-radius: 50%;
|
||||||
|
transform: translate(- $switch-focus-init-size / 2, - $switch-focus-init-size / 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.input {
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
opacity: 0;
|
||||||
|
|
||||||
|
&:focus:not(:active) {
|
||||||
|
+ .switch-on > .thumb:before {
|
||||||
|
@extend %thumb-focus;
|
||||||
|
background-color: $switch-on-focus-color;
|
||||||
|
box-shadow: 0 0 0 $switch-focus-diff $switch-on-focus-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ .switch-off > .thumb:before {
|
||||||
|
@extend %thumb-focus;
|
||||||
|
background-color: $switch-off-focus-color;
|
||||||
|
box-shadow: 0 0 0 $switch-focus-diff $switch-off-focus-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.disabled {
|
||||||
|
@extend .field;
|
||||||
|
|
||||||
|
.text {
|
||||||
|
color: $switch-disabled-text-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
.switch-on, .switch-off {
|
||||||
|
cursor: auto;
|
||||||
|
background: $switch-disabled-track-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
.thumb {
|
||||||
|
cursor: auto;
|
||||||
|
background-color: $switch-disabled-thumb-color;
|
||||||
|
border-color: transparent;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,47 +0,0 @@
|
||||||
@import '../constants'
|
|
||||||
|
|
||||||
SIZE = (SPACE / 1.25)
|
|
||||||
|
|
||||||
:local(.root)
|
|
||||||
position : relative
|
|
||||||
margin-bottom : SPACE
|
|
||||||
height : SIZE
|
|
||||||
width : WIDTH = (2.5 * SIZE)
|
|
||||||
background-color : DIVIDER
|
|
||||||
border-radius : SPACE
|
|
||||||
transition background-color ANIMATION_DURATION ANIMATION_EASE
|
|
||||||
> *
|
|
||||||
pointer-events : none
|
|
||||||
> span
|
|
||||||
position : absolute
|
|
||||||
top : -(SIZE / 5)
|
|
||||||
right : (SPACE)
|
|
||||||
width : (SIZE * 1.35)
|
|
||||||
height : (SIZE * 1.35)
|
|
||||||
border-radius : 50%
|
|
||||||
background-color : WHITE
|
|
||||||
transition-property background-color, box-shadow, right
|
|
||||||
transition-duration ANIMATION_DURATION
|
|
||||||
transition-timing-function ANIMATION_EASE
|
|
||||||
> label
|
|
||||||
display : block
|
|
||||||
margin-left : WIDTH + (SPACE / 2)
|
|
||||||
font-size : FONT_SIZE_SMALL
|
|
||||||
color : FORM_TEXT
|
|
||||||
|
|
||||||
// -- Style
|
|
||||||
&:not(.disabled)
|
|
||||||
cursor : pointer
|
|
||||||
> span
|
|
||||||
box-shadow : ZDEPTH_SHADOW_1
|
|
||||||
&.disabled
|
|
||||||
background-color : lighten(DIVIDER, 50%)
|
|
||||||
> span
|
|
||||||
background-color : DIVIDER
|
|
||||||
|
|
||||||
&.checked
|
|
||||||
background-color : alpha(PRIMARY, 25%)
|
|
||||||
> span
|
|
||||||
background-color : PRIMARY
|
|
||||||
right : 0
|
|
||||||
box-shadow : ZDEPTH_SHADOW_2
|
|
|
@ -0,0 +1,72 @@
|
||||||
|
@import "../variables";
|
||||||
|
|
||||||
|
$tab-text: $color-black !default;
|
||||||
|
$tab-text-color: unquote("rgb(#{$tab-text})") !default;
|
||||||
|
$tab-text-inactive-color: unquote("rgba(#{$tab-text}, 0.70)") !default;
|
||||||
|
$tab-pointer-height: .2 * $unit;
|
||||||
|
$tab-pointer-color: unquote("rgb(#{$color-primary})") !default;
|
||||||
|
$tab-navigation-border-color: $color-divider;
|
||||||
|
$tab-text-height: 1.4 * $unit;
|
||||||
|
$tab-label-height: 4.8 * $unit;
|
||||||
|
$tab-label-h-padding: 1.2 * $unit;
|
||||||
|
$tab-label-v-padding: ($tab-label-height - $tab-text-height) / 2;
|
||||||
|
$tab-label-disabled-opacity: .2;
|
||||||
|
|
||||||
|
.root {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navigation {
|
||||||
|
box-shadow: inset 0 -1px $tab-navigation-border-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label {
|
||||||
|
padding: $tab-label-v-padding $tab-label-h-padding;
|
||||||
|
font-size: $tab-text-height;
|
||||||
|
font-weight: $font-weight-semi-bold;
|
||||||
|
line-height: 1;
|
||||||
|
color: $tab-text-inactive-color;
|
||||||
|
text-transform: uppercase;
|
||||||
|
transition-timing-function: $animation-curve-default;
|
||||||
|
transition-duration: $animation-duration;
|
||||||
|
transition-property: box-shadow, color;
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
color: $tab-text-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.disabled {
|
||||||
|
opacity: $tab-label-disabled-opacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:not(.disabled) {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.pointer {
|
||||||
|
position: absolute;
|
||||||
|
width: 0;
|
||||||
|
height: $tab-pointer-height;
|
||||||
|
margin-top: - $tab-pointer-height;
|
||||||
|
background-color: $tab-pointer-color;
|
||||||
|
transition-timing-function: $animation-curve-default;
|
||||||
|
transition-duration: $animation-duration;
|
||||||
|
transition-property: left, width;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab {
|
||||||
|
padding: $tab-label-v-padding $tab-label-h-padding;
|
||||||
|
|
||||||
|
&:not(.active) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,43 +0,0 @@
|
||||||
@import '../constants'
|
|
||||||
|
|
||||||
:local(.root)
|
|
||||||
position : relative
|
|
||||||
> nav
|
|
||||||
box-shadow : inset 0 -1px DIVIDER
|
|
||||||
> label
|
|
||||||
padding : (OFFSET / 2) OFFSET
|
|
||||||
font-size : FONT_SIZE_TINY
|
|
||||||
font-weight : FONT_WEIGHT_BOLD
|
|
||||||
text-transform : Uppercase
|
|
||||||
color : TEXT_SECONDARY
|
|
||||||
transition-property : box-shadow, color
|
|
||||||
transition-duration : ANIMATION_DURATION
|
|
||||||
transition-timing-function : ANIMATION_EASE
|
|
||||||
&.active
|
|
||||||
color : TEXT
|
|
||||||
// box-shadow : inset 0 (-(OFFSET / 10)) PRIMARY
|
|
||||||
&.disabled
|
|
||||||
opacity : 0.2
|
|
||||||
&:not(.disabled)
|
|
||||||
cursor : pointer
|
|
||||||
&.hidden
|
|
||||||
display : none
|
|
||||||
|
|
||||||
:local(.pointer)
|
|
||||||
HEIGHT = (OFFSET / 10)
|
|
||||||
position : absolute
|
|
||||||
margin-left : -(OFFSET)
|
|
||||||
margin-top : -(HEIGHT)
|
|
||||||
height : HEIGHT
|
|
||||||
width : 128px
|
|
||||||
background-color : PRIMARY
|
|
||||||
transition-property : left, width
|
|
||||||
transition-duration : ANIMATION_DURATION
|
|
||||||
transition-timing-function : ANIMATION_EASE
|
|
||||||
|
|
||||||
:local(.tab)
|
|
||||||
padding : (OFFSET / 2) OFFSET
|
|
||||||
&:not(.active)
|
|
||||||
display : none
|
|
||||||
&.active
|
|
||||||
display : block
|
|
|
@ -1,5 +1,4 @@
|
||||||
/* global React */
|
import React from 'react';
|
||||||
|
|
||||||
import style from './style';
|
import style from './style';
|
||||||
|
|
||||||
export default React.createClass({
|
export default React.createClass({
|
||||||
|
@ -32,9 +31,9 @@ export default React.createClass({
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
let className = `${style.tab} ${this.props.className}`;
|
let className = `${style.tab} ${this.props.className}`;
|
||||||
if (this.props.active) className += ' active';
|
if (this.props.active) className += ` ${style.active}`;
|
||||||
if (this.props.disabled) className += ' disabled';
|
if (this.props.disabled) className += ` ${style.disabled}`;
|
||||||
if (this.props.hidden) className += ' hidden';
|
if (this.props.hidden) className += ` ${style.hidden}`;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section
|
<section
|
||||||
|
|
|
@ -1,19 +1,9 @@
|
||||||
/* global React */
|
import React from 'react';
|
||||||
|
import PureRenderMixin from 'react-addons-pure-render-mixin';
|
||||||
import { addons } from 'react/addons';
|
|
||||||
import style from './style';
|
import style from './style';
|
||||||
|
|
||||||
function _pointerPosition (index = 0, navigation) {
|
|
||||||
const label = navigation.children[index].getBoundingClientRect();
|
|
||||||
return {
|
|
||||||
top: `${navigation.getBoundingClientRect().height}px`,
|
|
||||||
left: `${label.left}px`,
|
|
||||||
width: `${label.width}px`
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export default React.createClass({
|
export default React.createClass({
|
||||||
mixins: [addons.PureRenderMixin],
|
mixins: [PureRenderMixin],
|
||||||
|
|
||||||
displayName: 'Tabs',
|
displayName: 'Tabs',
|
||||||
|
|
||||||
|
@ -39,7 +29,7 @@ export default React.createClass({
|
||||||
|
|
||||||
componentDidMount () {
|
componentDidMount () {
|
||||||
this.setState({
|
this.setState({
|
||||||
pointer: _pointerPosition(this.state.index, this.refs.navigation.getDOMNode())
|
pointer: this._pointerPosition(this.state.index, this.refs.navigation)
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -47,27 +37,45 @@ export default React.createClass({
|
||||||
const index = next_props.index || this.state.index;
|
const index = next_props.index || this.state.index;
|
||||||
this.setState({
|
this.setState({
|
||||||
index: index,
|
index: index,
|
||||||
pointer: _pointerPosition(index, this.refs.navigation.getDOMNode())
|
pointer: this._pointerPosition(index, this.refs.navigation)
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_pointerPosition (index = 0, navigation) {
|
||||||
|
const startPoint = this.refs.tabs.getBoundingClientRect().left;
|
||||||
|
const label = navigation.children[index].getBoundingClientRect();
|
||||||
|
|
||||||
|
return {
|
||||||
|
top: `${navigation.getBoundingClientRect().height}px`,
|
||||||
|
left: `${label.left - startPoint}px`,
|
||||||
|
width: `${label.width}px`
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
onClick (index) {
|
onClick (index) {
|
||||||
this.setState({
|
this.setState({
|
||||||
index: index,
|
index: index,
|
||||||
pointer: _pointerPosition(index, this.refs.navigation.getDOMNode())
|
pointer: this._pointerPosition(index, this.refs.navigation)
|
||||||
});
|
});
|
||||||
if (this.props.onChange) this.props.onChange(this);
|
if (this.props.onChange) this.props.onChange(this);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
renderLabels (labels) {
|
||||||
|
return labels.map((props) => {
|
||||||
|
return <label {...props}>{ props.label }</label>;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
let labels = [];
|
let labels = [];
|
||||||
|
|
||||||
const tabs = this.props.children.map((tab, index) => {
|
const tabs = this.props.children.map((tab, index) => {
|
||||||
let active = this.state.index === index;
|
let active = this.state.index === index;
|
||||||
|
let className = `${style.label} ${tab.props.className}`;
|
||||||
|
|
||||||
let className = tab.props.className;
|
if (active) className += ` ${style.active}`;
|
||||||
if (active) className += ' active';
|
if (tab.props.disabled) className += ` ${style.disabled}`;
|
||||||
if (tab.props.disabled) className += ' disabled';
|
if (tab.props.hidden) className += ` ${style.hidden}`;
|
||||||
if (tab.props.hidden) className += ' hidden';
|
|
||||||
|
|
||||||
labels.push({
|
labels.push({
|
||||||
className: className,
|
className: className,
|
||||||
|
@ -79,16 +87,15 @@ export default React.createClass({
|
||||||
return React.cloneElement(tab, {active: active, key: index, tabIndex: index });
|
return React.cloneElement(tab, {active: active, key: index, tabIndex: index });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let className = style.root;
|
||||||
|
if (this.props.className) className += ` ${this.props.className}`;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div data-react-toolbox='tabs' ref='tabs' className={className} data-flex='vertical'>
|
||||||
data-react-toolbox='tabs'
|
<nav className={style.navigation} ref='navigation' data-flex='horizontal'>
|
||||||
className={style.root + ' ' + this.props.className}
|
{ this.renderLabels(labels) }
|
||||||
data-flex='vertical'
|
|
||||||
>
|
|
||||||
<nav ref='navigation' data-flex='horizontal'>
|
|
||||||
{ labels.map((props) => { return <label {...props}>{props.label}</label>; }) }
|
|
||||||
</nav>
|
</nav>
|
||||||
<span className={style.pointer} style={this.state.pointer}></span>
|
<span className={style.pointer} style={this.state.pointer} />
|
||||||
{ tabs }
|
{ tabs }
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,13 +1,12 @@
|
||||||
/* global React */
|
import React from 'react';
|
||||||
|
import PureRenderMixin from 'react-addons-pure-render-mixin';
|
||||||
import { addons } from 'react/addons';
|
import style from './style';
|
||||||
import css from './style';
|
|
||||||
import time from '../utils/time';
|
import time from '../utils/time';
|
||||||
import Clock from '../clock';
|
import Clock from '../clock';
|
||||||
import Dialog from '../dialog';
|
import Dialog from '../dialog';
|
||||||
|
|
||||||
export default React.createClass({
|
export default React.createClass({
|
||||||
mixins: [addons.PureRenderMixin],
|
mixins: [PureRenderMixin],
|
||||||
|
|
||||||
displayName: 'TimePickerDialog',
|
displayName: 'TimePickerDialog',
|
||||||
|
|
||||||
|
@ -31,8 +30,8 @@ export default React.createClass({
|
||||||
display: 'hours',
|
display: 'hours',
|
||||||
time: this.props.initialTime,
|
time: this.props.initialTime,
|
||||||
actions: [
|
actions: [
|
||||||
{ label: 'Cancel', type: 'flat accent', onClick: this.onTimeCancel },
|
{ label: 'Cancel', className: style.button, onClick: this.onTimeCancel },
|
||||||
{ label: 'Ok', type: 'flat accent', onClick: this.onTimeSelected }
|
{ label: 'Ok', className: style.button, onClick: this.onTimeSelected }
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
@ -77,25 +76,28 @@ export default React.createClass({
|
||||||
|
|
||||||
renderAMPMLabels () {
|
renderAMPMLabels () {
|
||||||
if (this.props.format === 'ampm') {
|
if (this.props.format === 'ampm') {
|
||||||
return (<div className={css.ampm}>
|
return (
|
||||||
<span className={css.am} onClick={this.toggleTimeMode}>AM</span>
|
<div className={style.ampm}>
|
||||||
<span className={css.pm} onClick={this.toggleTimeMode}>PM</span>
|
<span className={style.am} onClick={this.toggleTimeMode}>AM</span>
|
||||||
</div>);
|
<span className={style.pm} onClick={this.toggleTimeMode}>PM</span>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
let className = ` display-${this.state.display}`;
|
const display = `display-${this.state.display}`;
|
||||||
className += ` format-${time.getTimeMode(this.state.time)}`;
|
const format = `format-${time.getTimeMode(this.state.time)}`;
|
||||||
|
const className = `${style.dialog} ${style[display]} ${style[format]}`;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog ref="dialog" className={className} type={css.dialog} actions={this.state.actions}>
|
<Dialog ref="dialog" className={className} type="custom" actions={this.state.actions}>
|
||||||
<header className={css.header}>
|
<header className={style.header}>
|
||||||
<span className={css.hours} onClick={this.displayHours}>
|
<span className={style.hours} onClick={this.displayHours}>
|
||||||
{ ('0' + this.formatHours()).slice(-2) }
|
{ ('0' + this.formatHours()).slice(-2) }
|
||||||
</span>
|
</span>
|
||||||
<span className={css.separator}>:</span>
|
<span className={style.separator}>:</span>
|
||||||
<span className={css.minutes} onClick={this.displayMinutes}>
|
<span className={style.minutes} onClick={this.displayMinutes}>
|
||||||
{ ('0' + this.state.time.getMinutes()).slice(-2) }
|
{ ('0' + this.state.time.getMinutes()).slice(-2) }
|
||||||
</span>
|
</span>
|
||||||
{ this.renderAMPMLabels() }
|
{ this.renderAMPMLabels() }
|
||||||
|
@ -105,7 +107,8 @@ export default React.createClass({
|
||||||
display={this.state.display}
|
display={this.state.display}
|
||||||
format={this.props.format}
|
format={this.props.format}
|
||||||
initialTime={this.props.initialTime}
|
initialTime={this.props.initialTime}
|
||||||
onChange={this.onClockChange} />
|
onChange={this.onClockChange}
|
||||||
|
/>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
/* global React */
|
import React from 'react';
|
||||||
|
import PureRenderMixin from 'react-addons-pure-render-mixin';
|
||||||
import { addons } from 'react/addons';
|
|
||||||
import time from '../utils/time';
|
import time from '../utils/time';
|
||||||
|
import style from './style';
|
||||||
|
import events from '../utils/events';
|
||||||
import Input from '../input';
|
import Input from '../input';
|
||||||
import TimeDialog from './dialog';
|
import TimeDialog from './dialog';
|
||||||
|
|
||||||
export default React.createClass({
|
export default React.createClass({
|
||||||
mixins: [addons.PureRenderMixin],
|
mixins: [PureRenderMixin],
|
||||||
|
|
||||||
displayName: 'TimePicker',
|
displayName: 'TimePicker',
|
||||||
|
|
||||||
|
@ -32,7 +33,8 @@ export default React.createClass({
|
||||||
this.setState({value: newTime});
|
this.setState({value: newTime});
|
||||||
},
|
},
|
||||||
|
|
||||||
openTimeDialog () {
|
openTimeDialog (event) {
|
||||||
|
events.pauseEvent(event);
|
||||||
this.refs.dialog.show();
|
this.refs.dialog.show();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -48,19 +50,22 @@ export default React.createClass({
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div data-react-toolbox='time-picker'>
|
||||||
<Input
|
<Input
|
||||||
ref="input"
|
ref='input'
|
||||||
type="text"
|
type='text'
|
||||||
disabled={true}
|
className={style.input}
|
||||||
onClick={this.openTimeDialog}
|
readOnly={true}
|
||||||
placeholder="Pick up time"
|
onMouseDown={this.openTimeDialog}
|
||||||
value={this.formatTime()} />
|
placeholder='Pick up time'
|
||||||
|
value={this.formatTime()}
|
||||||
|
/>
|
||||||
<TimeDialog
|
<TimeDialog
|
||||||
ref="dialog"
|
ref='dialog'
|
||||||
initialTime={this.state.value}
|
initialTime={this.state.value}
|
||||||
format={this.props.format}
|
format={this.props.format}
|
||||||
onTimeSelected={this.onTimeSelected} />
|
onTimeSelected={this.onTimeSelected}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,82 @@
|
||||||
|
@import "../variables";
|
||||||
|
|
||||||
|
$timepicker-primary: $color-primary;
|
||||||
|
$timepicker-primary-contrast: $color-primary-contrast;
|
||||||
|
$timepicker-primary-dark: $color-primary-dark;
|
||||||
|
$timepicker-primary-color: unquote("rgb(#{$timepicker-primary})") !default;
|
||||||
|
$timepicker-primary-hover-color: unquote("rgba(#{$timepicker-primary}, 0.20)") !default;
|
||||||
|
$timepicker-primary-contrast-color: unquote("rgb(#{$timepicker-primary-contrast})") !default;
|
||||||
|
$timepicker-primary-dark-color: unquote("rgb(#{$timepicker-primary-dark})") !default;
|
||||||
|
$timepicker-ampm-height: 2.2 * $unit;
|
||||||
|
$timepicker-ampm-width: 4 * $unit;
|
||||||
|
$timepicker-dialog-width: 30 * $unit;
|
||||||
|
|
||||||
|
.input > [role="input"] {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
padding: 10px;
|
||||||
|
font-size: 52px;
|
||||||
|
color: $timepicker-primary-contrast-color;
|
||||||
|
text-align: center;
|
||||||
|
background: $timepicker-primary-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hours, .minutes {
|
||||||
|
display: inline-block;
|
||||||
|
cursor: pointer;
|
||||||
|
opacity: .6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.separator {
|
||||||
|
margin: 0 5px;
|
||||||
|
opacity: .6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ampm {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
right: 20px;
|
||||||
|
width: $timepicker-ampm-width;
|
||||||
|
height: $timepicker-ampm-height * 2;
|
||||||
|
margin-top: - $timepicker-ampm-height;
|
||||||
|
font-size: 16px;
|
||||||
|
line-height: $timepicker-ampm-height;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.am, .pm {
|
||||||
|
display: block;
|
||||||
|
cursor: pointer;
|
||||||
|
opacity: .6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog {
|
||||||
|
> [role="content"] {
|
||||||
|
width: $timepicker-dialog-width;
|
||||||
|
|
||||||
|
> [role="body"] {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
> [role="navigation"] > .button {
|
||||||
|
color: $timepicker-primary-color;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: $timepicker-primary-hover-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus:not(:active) {
|
||||||
|
background: $timepicker-primary-hover-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.display-hours .hours, &.display-minutes .minutes, &.format-am .am,
|
||||||
|
&.format-pm .pm {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,60 +0,0 @@
|
||||||
@import '../constants'
|
|
||||||
|
|
||||||
AMPM_HEIGHT = 22px
|
|
||||||
AMPM_WIDTH = 40px
|
|
||||||
PICKER_WIDTH = 330px
|
|
||||||
|
|
||||||
// Picker dialog
|
|
||||||
:local(.dialog)
|
|
||||||
padding : 0
|
|
||||||
width : PICKER_WIDTH
|
|
||||||
> nav
|
|
||||||
margin-top : 0
|
|
||||||
padding-bottom : 10px
|
|
||||||
|
|
||||||
:local(.header)
|
|
||||||
background : ACCENT
|
|
||||||
color : WHITE
|
|
||||||
font-size : 52px
|
|
||||||
padding : 10px
|
|
||||||
text-align : center
|
|
||||||
position : relative
|
|
||||||
width : 100%
|
|
||||||
|
|
||||||
:local(.hours), :local(.minutes)
|
|
||||||
cursor : pointer
|
|
||||||
display : inline-block
|
|
||||||
opacity : .6
|
|
||||||
|
|
||||||
:local(.separator)
|
|
||||||
margin : 0 5px
|
|
||||||
opacity : .6
|
|
||||||
|
|
||||||
:local(.ampm)
|
|
||||||
font-size : 16px
|
|
||||||
height : AMPM_HEIGHT * 2
|
|
||||||
line-height : AMPM_HEIGHT
|
|
||||||
margin-top : - AMPM_HEIGHT
|
|
||||||
position : absolute
|
|
||||||
right : 20px
|
|
||||||
text-align : center
|
|
||||||
top : 50%
|
|
||||||
width : AMPM_WIDTH
|
|
||||||
|
|
||||||
:local(.am), :local(.pm)
|
|
||||||
cursor : pointer
|
|
||||||
display : block
|
|
||||||
opacity : .6
|
|
||||||
|
|
||||||
// Modifiers
|
|
||||||
:local(.dialog).display-hours :local(.hours)
|
|
||||||
opacity : 1
|
|
||||||
|
|
||||||
:local(.dialog).display-minutes :local(.minutes)
|
|
||||||
opacity : 1
|
|
||||||
|
|
||||||
:local(.dialog).format-am :local(.am)
|
|
||||||
opacity : 1
|
|
||||||
|
|
||||||
:local(.dialog).format-pm :local(.pm)
|
|
||||||
opacity : 1
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* global React */
|
import React from 'react';
|
||||||
|
import TestUtils from 'react-addons-test-utils';
|
||||||
const TestUtils = React.addons.TestUtils;
|
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,67 @@
|
||||||
|
@import "./colors";
|
||||||
|
|
||||||
|
//-- Color configuration
|
||||||
|
$color-divider: unquote("rgb(#{$palette-grey-200})") !default;
|
||||||
|
$color-background: unquote("rgb(#{$color-white})") !default;
|
||||||
|
$color-overlay: unquote("rgb(#{$color-black})");
|
||||||
|
$color-overlay-opacity: 0.5;
|
||||||
|
$color-text: unquote("rgb(#{$palette-grey-900})") !default;
|
||||||
|
$color-text-secondary: unquote("rgb(#{$palette-grey-600})") !default;
|
||||||
|
|
||||||
|
$color-primary: $palette-blue-500 !default;
|
||||||
|
$color-primary-dark: $palette-blue-700 !default;
|
||||||
|
$color-accent: $palette-pink-a200 !default;
|
||||||
|
$color-accent-dark: $palette-pink-700 !default;
|
||||||
|
$color-primary-contrast: $color-dark-contrast !default;
|
||||||
|
$color-accent-contrast: $color-dark-contrast !default;
|
||||||
|
|
||||||
|
//-- Unit
|
||||||
|
$unit: 1rem;
|
||||||
|
|
||||||
|
// Sizes
|
||||||
|
$input-height: 3.2 * $unit;
|
||||||
|
$offset: 1.6 * $unit;
|
||||||
|
$border-radius: 0.2 * $unit;
|
||||||
|
$items-overflow-max-height: 45vh;
|
||||||
|
|
||||||
|
// -- Fonts
|
||||||
|
$preferred-font: "Roboto", "Helvetica", "Arial", sans-serif !default;
|
||||||
|
$font-size: 1.6 * $unit !default;
|
||||||
|
$font-size-tiny: 1.2 * $unit !default;
|
||||||
|
$font-size-small: 1.4 * $unit !default;
|
||||||
|
$font-size-normal: $font-size !default;
|
||||||
|
$font-size-big: 1.8 * $unit !default;
|
||||||
|
$font-weight-thin: 300 !default;
|
||||||
|
$font-weight-normal: 400 !default;
|
||||||
|
$font-weight-semi-bold: 500 !default;
|
||||||
|
$font-weight-bold: 700 !default;
|
||||||
|
|
||||||
|
//-- Shadows
|
||||||
|
$shadow-key-umbra-opacity: 0.2 !default;
|
||||||
|
$shadow-key-penumbra-opacity: 0.14 !default;
|
||||||
|
$shadow-ambient-shadow-opacity: 0.12 !default;
|
||||||
|
|
||||||
|
//-- Depth Shadows
|
||||||
|
$zdepth-shadow-1: 0 1px 6px rgba(0,0,0,0.12), 0 1px 4px rgba(0,0,0,0.24);
|
||||||
|
$zdepth-shadow-2: 0 3px 10px rgba(0,0,0,0.16), 0 3px 10px rgba(0,0,0,0.23);
|
||||||
|
$zdepth-shadow-3: 0 10px 30px rgba(0,0,0,0.19), 0 6px 10px rgba(0,0,0,0.23);
|
||||||
|
$zdepth-shadow-4: 0 14px 45px rgba(0,0,0,0.25), 0 10px 18px rgba(0,0,0,0.22);
|
||||||
|
$zdepth-shadow-5: 0 19px 60px rgba(0,0,0,0.30), 0 15px 20px rgba(0,0,0,0.22);
|
||||||
|
|
||||||
|
//-- Animation
|
||||||
|
$animation-duration: .35s;
|
||||||
|
$animation-delay: $animation-duration / 5;
|
||||||
|
$animation-curve-fast-out-slow-in: cubic-bezier(0.4, 0, 0.2, 1) !default;
|
||||||
|
$animation-curve-linear-out-slow-in: cubic-bezier(0, 0, 0.2, 1) !default;
|
||||||
|
$animation-curve-fast-out-linear-in: cubic-bezier(0.4, 0, 1, 1) !default;
|
||||||
|
$animation-curve-default: $animation-curve-fast-out-slow-in !default;
|
||||||
|
|
||||||
|
//-- Input spaces
|
||||||
|
$input-margin-bottom: $unit * .8;
|
||||||
|
|
||||||
|
//-- Indexes
|
||||||
|
$z-index-higher: 200;
|
||||||
|
$z-index-high: 100;
|
||||||
|
$z-index-normal: 1;
|
||||||
|
$z-index-low: -100;
|
||||||
|
$z-index-lower: -200;
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue