UNPKG

@enact/ui

Version:

A collection of simplified unstyled cross-platform UI components for Enact

464 lines (411 loc) 15.1 kB
@import "./utils.less"; @import "./variables.less"; // Disabled elements .disabled(@rules; @target) when (isruleset(@rules)) and (@target = parent) { [disabled] { @rules(); } } .disabled(@rules) when (isruleset(@rules)) { &[disabled] { @rules(); } } .enact-composite() { transform: translateZ(0); will-change: transform; } // Applies RTL-compatible start and end position to a selector // Simple "when" here just assumes that if the first argument is a list with more than 1 entry, // then units are correct. If it's just 1, then we verify the value is a number (measurement). .position-start-end (@trbl; @target: "") when (length(@trbl) > 1) or (@target = parent) or (@target = self) or (@target = "") { .position(@trbl); .enact-locale-rtl({ .position( // Note: swapping left and right values .extract(@trbl; top)[] .extract(@trbl; left)[] .extract(@trbl; bottom)[] .extract(@trbl; right)[] ); }; @target); } .position-start-end (@start; @end; @target: "") when (default()) { left: @start; right: @end; .enact-locale-rtl({ left: @end; right: @start; }, @target); } // Applies RTL-compatible start and end margins to a selector .margin-start-end (@trbl; @target: "") when (length(@trbl) > 1) or (@target = parent) or (@target = self) or (@target = "") { margin: @trbl; .enact-locale-rtl({ margin: // Note: swapping left and right values .extract(@trbl; top)[] .extract(@trbl; left)[] .extract(@trbl; bottom)[] .extract(@trbl; right)[] ; }; @target); } .margin-start-end(@start; @end; @target: "") when (default()) { margin-left: @start; margin-right: @end; .enact-locale-rtl({ margin-left: @end; margin-right: @start; }, @target); } // Applies RTL-compatible start and end padding to a selector .padding-start-end (@trbl; @target: "") when (length(@trbl) > 1) or (@target = parent) or (@target = self) or (@target = "") { padding: @trbl; .enact-locale-rtl({ padding: // Note: swapping left and right values .extract(@trbl; top)[] .extract(@trbl; left)[] .extract(@trbl; bottom)[] .extract(@trbl; right)[] ; }; @target); } .padding-start-end(@start; @end; @target: "") when (default()) { padding-left: @start; padding-right: @end; .enact-locale-rtl({ padding-left: @end; padding-right: @start; }, @target); } // NOTE: Until we are able to automatically remove these JSDoc-style comments, they should remain LESS-commented // /** // * Removes the margin from the appropriate side of the child components that touch the edges of the // * component this is applied to. This respects both LTR and RTL modes. // */ .remove-margin-on-edge-children() { > :first-child { margin-inline-start: 0; } > :last-child { margin-inline-end: 0; } } // /** // * Removes the padding from the appropriate side of the child components that touch the edges of the // * component this is applied to. This respects both LTR and RTL modes. // */ .remove-padding-on-edge-children() { > :first-child { padding-inline-start: 0; } > :last-child { padding-inline-end: 0; } } .full-screen-video-player() { position: static !important; display: block !important; margin: 0; } .hide-full-screen-ancestor() { position: absolute !important; overflow: visible !important; padding: 0 !important; margin: 0 !important; width: 100% !important; height: 100% !important; } .input-placeholder(@rule) { &::placeholder { @rule(); } } // Assign font-kerning rules in a non-proprietary way. Default value being "normal", to enable kerning. .font-kerning(@val: normal) { font-kerning: @val; } .vendor-fullscreen(@rule) { &:fullscreen { @rule(); } } .vendor-opacity(@opacity) { opacity: @opacity; } // Shorthand for positioning code .position (@t, @r, @b, @l) { top: @t; right: @r; bottom: @b; left: @l; } .position (@t, @rl, @b) { .position(@t, @rl, @b, @rl); } .position (@tb, @rl) { .position(@tb, @rl, @tb, @rl); } .position (@trbl) when (length(@trbl) = 4) { .position( extract(@trbl, 1), extract(@trbl, 2), extract(@trbl, 3), extract(@trbl, 4) ); } .position (@trbl) when (length(@trbl) = 3) { .position( extract(@trbl, 1), extract(@trbl, 2), extract(@trbl, 3) ); } .position (@trbl) when (length(@trbl) = 2) { .position( extract(@trbl, 1), extract(@trbl, 2) ); } .position (@trbl) when (length(@trbl) = 1) { .position(@trbl, @trbl, @trbl, @trbl); } .border-box() { box-sizing: border-box; } // Helpful debugging way to understand how LESS variables are being interpreted .debugLessTypes(@value) { :global(.debugLessTypes) { value: @value; isnumber: isnumber(@value); isstring: isstring(@value); iscolor: iscolor(@value); iskeyword: iskeyword(@value); isurl: isurl(@value); ispixel: ispixel(@value); isem: isem(@value); ispercentage: ispercentage(@value); isruleset: isruleset(@value); } } // // Mixin classes supporting advanced text // // /** // * Generate a pair of @font-face rules for a given name and "collection" of locale fonts. // * // * This creates two (2) referenceable font-family names, one that "stacks" onto the provided "base" // * name, the other suffixed with the locale name. E.g. "FontName" and "FontName Locale". // * // * Example: // * ``` // * @fonts: { // * as: local("LG Smart UI Bengali"); // same as `bn` // * bn: local("LG Smart UI Bengali"); // * en-JP: local("LG Smart UI JP"), local("LG Display_JP_Bold") 700; // same as `ja` // * ja: local("LG Smart UI JP"), local("LG Display_JP_Bold") 700; // Generates 2 entries, one for JP set to "normal" (default) weight and another for JP_Bold set to 700 weight // * ur: local("LG Smart UI_Urdu") normal 300 600 700; // Generates 4 entries, one for each weight // * }; // * ``` // * // * List of supported "options" per locale key, in the following order: // * * single font source - Typically a reference to a local() font or a url() font. // * * font-weight - Optional, Numbers (100, 500, 700, etc) and keywords (normal, bold, etc) are supported. // * Empty-string represents "null". This excludes the font-weight rule from the generated code. // * Multiple weights can be supplied to generate multiple sets of face rules for a single source file // * * font-style - Optional, Keywords (normal, italic, etc) are supported. // * // * OPTIONALLY: repeat the options above after a comma (,) for multiple weights/styles/options based on the same name. // * // * @param {String} @baseName The name used as the basis for the generated font-family. // * @param {Object} @f Object of keys with values detailing the font variants and options. // */ .buildLocaleFont(@fontName; @locale; @src; @rules) when (isruleset(@rules)) { .buildFontFace("@{fontName} @{locale}"; @src; @rules); .buildFontFace(@fontName; @src; @rules); } .buildLocaleFont(@fontName; @locale; @args) when (default()) { @src: extract(@args, 1); @argLast: extract(@args, length(@args)); // optional style value @styleExists: boolean((@argLast = italic) or (@argLast = oblique)); // List all valid font-style values here (except for "normal" since that is a shared keyword with font-weight) @style: if(@styleExists, @argLast); @lastWeightArgIndex: if(@styleExists, length(@args) - 1, length(@args)); // It's possible this could get confused if "normal" or "bold" is used as the last weight. Please use a number as the last weight. // Please retain the following comment for future debugging purposes. This gives insight into how the definition values are being interpreted. // :global(.debug-buildLocaleFont@{fontName}-@{locale}) { // fontName: @fontName; // locale: @locale; // args: @args; // args-count: length(@args); // last-weight-arg-index: @lastWeightArgIndex; // src: @src; // styleExists: @styleExists; // style: @style; // } // Run when there are 2 or more arguments each(range(2, @lastWeightArgIndex), .(@argIndex) { @weight: extract(@args, @argIndex); .buildFontFace("@{fontName} @{locale}"; @src; @weight; @style); .buildFontFace(@fontName; @src; @weight; @style); }); // Run when there are 1 or fewer arguments & when (length(@args) <= 1) { // There aren't any additional arguments, so weight and style can be safely omitted from the following calls .buildFontFace("@{fontName} @{locale}"; @src); .buildFontFace(@fontName; @src); } }; .buildLocaleFonts(@fontName; @f) { each(@f, .(@specs, @locale) { // Determine if we're working with a collection of font definitions or an individual definition @isCollection: if(((length(@specs) > 1) and ((length(extract(@specs, 1)) > 1) or (length(extract(@specs, 2)) > 1))), true, false); // :global(.debug-buildLocaleFonts-@{locale}) { // is-collection: @isCollection; // } // Interpret collections of font definitions: [(set1) (set2) (set3)] & when (@isCollection) { each(@specs, { .buildLocaleFont(@fontName; @locale; @value); }); } // Interpret individual font definitions: (set1) & when (not(@isCollection)) { .buildLocaleFont(@fontName; @locale; @specs); } // .debugLessTypes(@specs); // Note: The above `when` code will ignore definitions like the following, because the way // LESS works, it can't (at this time) differentiate between a space separated list and a // comma separated list, making it impossible to differentiate a single set of font rules // with multiple values vs multiple sets with a single value in each. // { // nameRepeat: local("name"), local("name2"); // } // Ex: `local("name") 400` vs `local("name"), local("name2")` // In this case, only the first value will be used, second, ignored. }); }; // /** // * Generate a single @font-face rule. // * // * List of supported "options" per locale key, in the following order: // * @param {String} font-family name The generated font name, referenceable via // * `font-family: <name>;` in normal CSS. // * @param {URL} single font source Typically a reference to a local() font or a url() font. // * @param {Number|Keyword|""} font-weight Optional, Numbers (100, 500, 700, etc) and keywords // * (normal, bold, etc) are supported. Empty-string represents // * "null" or default. This excludes the weight rule from the generated code. // * @param {Keyword} font-style Optional, Keywords (normal, italic, etc) are supported. // */ .buildFontFace(@name; @src; @rules) when (isruleset(@rules)) { @font-face { font-family: @name; src: @src; @rules(); } } // `length()` below refers to specifying font-weight ranges: `600 900`. // Ex: // .buildFontFace("fontName"; local("name"); 400 600); // -> .buildFontFace("fontName"; local("name"); 400); .buildFontFace("fontName"; local("name"); 600); // .buildFontFace("fontName"; local("name"); 400 600; normal); // -> .buildFontFace("fontName"; local("name"); 400; normal); .buildFontFace("fontName"; local("name"); 600; normal); .buildFontFace(@name; @src; @weight: normal; @style: "") when (length(@weight) > 1) { each(@weight, { .buildFontFace(@name; @src; @value; @style); }); } // The default version of this mixin (below) is the shorthand version, which rearranges its arguments into the format the above mixin expects. .buildFontFace(@name; @src; @weight: normal; @style: "") when (default()) { .buildFontFace(@name; @src; { // Conditionally add the following & when ((iskeyword(@weight)) or (isnumber(@weight))) { font-weight: @weight; } & when (iskeyword(@style)) { font-style: @style; } }); } // // Locale Mixins // // .enact-locale-line-height() // // Assign line-height rules specifically to the languages designated // as needing special support for tall-glyphs. // // Set line-height for normal and tallglyphs with 1 list argument // Ex: // .enact-locale-line-height(1.4em 1.6em); // Or: // @lineheight: 1.4em 1.6em; // .enact-locale-line-height(@lineheight); .enact-locale-line-height(@both; @target: normal) when (length(@both) = 2) { .enact-locale-tallglyph(line-height; @both; @target); } // .enact-locale-tallglyph() // // Rulename and a normal value followed by a tallglyph value (3 arguments) // Ex: // .enact-locale-tallglyph(font-size; 1.4em; 1.6em); -> normal font-size: 1.4em; tallglyphs font-size: 1.6em; .enact-locale-tallglyph(@rule; @normal; @tallglyph; @target) when (iskeyword(@rule)) { @{rule}: @normal; .enact-locale-tallglyph(@rule; @tallglyph; @target); } // Rulename and 2 value second variable (2 arguments, 2nd being a list) // Ex: // .enact-locale-tallglyph(font-size; 1.4em 1.6em); -> normal font-size: 1.4em; tallglyphs font-size: 1.6em; // Or: // @fontsize: 1.4em 1.6em; // .enact-locale-tallglyph(font-size, @fontsize); -> normal font-size: 1.4em; tallglyphs font-size: 1.6em; .enact-locale-tallglyph(@rule; @val; @target: normal) when (iskeyword(@rule)) and (length(@val) = 2) { @{rule}: extract(@val, 1); .enact-locale-tallglyph(@rule; extract(@val, 2); @target); } // Rulename and a tallglyph value // Ex: // .enact-locale-tallglyph(font-size; 1.6em); -> tallglyphs font-size: 1.6em; .enact-locale-tallglyph(@rule; @val; @target: normal) when (iskeyword(@rule)) and (default()) { .enact-locale-tallglyph({ @{rule}: @val; }, @target); } // Accept a ruleset and apply it to the list of tall-glyph languages // Ex: // .enact-locale-tallglyph({ // font-size: 1.6em; // }); .enact-locale-tallglyph(@rules; @target: normal) when (isruleset(@rules)) and (default()) { each(@locale-tallglyph-languages, { // Take each language in the list, apply the @rules to them. // @value is used to generate an appropriate selector for the @rules. // Ex: `.enact-locale-th & { @rules(); }` .enact-locale(@value; @rules; @target); }); } // Assign rules specifically to RTL locales with a convenient shorthand. // Apply these rules to the current selector, not the general parent. .enact-locale-rtl(@rules; @target) when (isruleset(@rules)) and (@target = self) { .enact-locale(right-to-left; @rules; @target); } // Assign rules specifically to RTL locales with a convenient shorthand. .enact-locale-rtl(@rules; @target: normal) when (isruleset(@rules)) and (default()) { .enact-locale(right-to-left; @rules; @target); } // Generates an appropriate selector given the locale-target, and injects the given rules into it. // Apply these rules to the current selector, not the general parent. .enact-locale(@locale-target; @rules; @target) when (iskeyword(@locale-target)) and (isruleset(@rules)) and (@target = self) { &:global(.enact-locale-@{locale-target}) { @rules(); } } // Generates an appropriate selector given the locale-target, and injects the given rules into it. .enact-locale(@locale-target; @rules; @target: normal) when (iskeyword(@locale-target)) and (isruleset(@rules)) and (default()) { :global(.enact-locale-@{locale-target}) & { @rules(); } } .locale-japanese-line-break() { .enact-locale(ja; { line-break: strict; }); }