@ahrowe/ui 0.47.0 → 0.47.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +9 -0
- package/dist/esm/common/animatedIcon/animatedIcon.module.mjs.map +1 -1
- package/dist/esm/common/copyButton/copyButton.module.mjs.map +1 -1
- package/dist/esm/common/input/input.module.mjs.map +1 -1
- package/dist/esm/common/numberInput/numberInput.module.mjs +1 -1
- package/dist/esm/common/numberInput/numberInput.module.mjs.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/style.css +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# @ahrowe/ui
|
|
2
2
|
|
|
3
|
+
## 0.47.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 236e8ea: Search's magnifier and clear icon, and CopyButton's icon, keep their size when FontAwesome's stylesheet loads after the library's, as under Vite's dev server, instead of rendering smaller and too high
|
|
8
|
+
- c8d9cda: Fixed CopyButton's hidden status text lengthening the page when the button sits in a scroll container without a positioned ancestor
|
|
9
|
+
- 236e8ea: Input's placeholder and resting label start exactly where the typed text does, instead of 0.5px to its left
|
|
10
|
+
- 236e8ea: Input's suffix, placeholder and resting label share the baseline of the typed text instead of sitting 1px above it
|
|
11
|
+
|
|
3
12
|
## 0.47.0
|
|
4
13
|
|
|
5
14
|
### Minor Changes
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"animatedIcon.module.mjs","names":[],"sources":["../../../../package/common/animatedIcon/animatedIcon.module.pcss"],"sourcesContent":[".animatedIcon {\n position: relative;\n display: inline-block;\n width: 1em;\n height: 1em;\n\n /* Fab's original technique: a single shared rotation on the whole icon, not per layer — both\n the outgoing and incoming icon sit at the exact same angle at every instant, only their\n opacity differs, which is what makes the spin read as one coherent piece rather than two\n icons independently rotating past each other. Always a further full turn per step (not\n Fab's 225°, which only worked there because its \"+\" icon looks identical rotated 45°) so an\n arbitrary icon always lands back upright, no matter how many times it's toggled. A real\n `transition`, so retapping mid-spin reverses smoothly from wherever it currently is instead\n of snapping. */\n &-spin {\n transition: transform var(--animated-icon-duration, 200ms) ease;\n transform: rotate(var(--animated-icon-spin-rotation, 0deg));\n\n /* The wrapper alone carries the rotation in this variant — the two layers underneath it\n only need to crossfade, not rotate individually. */\n .animatedIcon-layer {\n &:first-child,\n &:last-child {\n transform: none;\n }\n }\n }\n\n /* Two layers, always both mounted — never conditionally rendered. A `transition` only\n retargets smoothly when the property changes on an element already on screen; a freshly-\n mounted element with its \"final\" state applied in the same paint has no \"from\" state to\n animate from. Keeping both layers permanently in the DOM (like Fab does) and only ever\n toggling which one is `-front` is what makes this cancel cleanly mid-transition instead of\n jumping or finishing a stale animation. */\n &-layer {\n position: absolute;\n inset: 0;\n
|
|
1
|
+
{"version":3,"file":"animatedIcon.module.mjs","names":[],"sources":["../../../../package/common/animatedIcon/animatedIcon.module.pcss"],"sourcesContent":[".animatedIcon {\n position: relative;\n display: inline-block;\n width: 1em;\n height: 1em;\n\n /* Fab's original technique: a single shared rotation on the whole icon, not per layer — both\n the outgoing and incoming icon sit at the exact same angle at every instant, only their\n opacity differs, which is what makes the spin read as one coherent piece rather than two\n icons independently rotating past each other. Always a further full turn per step (not\n Fab's 225°, which only worked there because its \"+\" icon looks identical rotated 45°) so an\n arbitrary icon always lands back upright, no matter how many times it's toggled. A real\n `transition`, so retapping mid-spin reverses smoothly from wherever it currently is instead\n of snapping. */\n &-spin {\n transition: transform var(--animated-icon-duration, 200ms) ease;\n transform: rotate(var(--animated-icon-spin-rotation, 0deg));\n\n /* The wrapper alone carries the rotation in this variant — the two layers underneath it\n only need to crossfade, not rotate individually. */\n .animatedIcon-layer {\n &:first-child,\n &:last-child {\n transform: none;\n }\n }\n }\n\n /* Two layers, always both mounted — never conditionally rendered. A `transition` only\n retargets smoothly when the property changes on an element already on screen; a freshly-\n mounted element with its \"final\" state applied in the same paint has no \"from\" state to\n animate from. Keeping both layers permanently in the DOM (like Fab does) and only ever\n toggling which one is `-front` is what makes this cancel cleanly mid-transition instead of\n jumping or finishing a stale animation. */\n &-layer {\n position: absolute;\n inset: 0;\n opacity: 0;\n transition:\n opacity var(--animated-icon-duration, 200ms) ease,\n transform var(--animated-icon-duration, 200ms) ease;\n\n /* Fixed per-layer resting pose (not per-toggle) — the first layer always approaches/leaves\n through +90°, the second always through -90°, so which direction a given swap rotates in\n depends only on which layer is taking over, the same way Fab's own icon always rotates\n between two fixed angles rather than accumulating. */\n &:first-child {\n transform: rotate(90deg) scale(0.5);\n\n &.animatedIcon-layer-front {\n transform: none;\n }\n }\n\n &:last-child {\n transform: rotate(-90deg) scale(0.5);\n\n &.animatedIcon-layer-front {\n transform: none;\n }\n }\n\n &-front {\n opacity: 1;\n }\n\n /* Two classes: FontAwesome injects `.svg-inline--fa { width; height }` at runtime, and against\n one class the stylesheet that happened to load last would decide the icon's size. */\n .animatedIcon & {\n width: 100%;\n height: 100%;\n }\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .animatedIcon-spin,\n .animatedIcon-layer {\n transition: none;\n }\n}\n"],"mappings":""}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"copyButton.module.mjs","names":[],"sources":["../../../../package/common/copyButton/copyButton.module.pcss"],"sourcesContent":[".copyButton-status {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n border: 0;\n clip-path: inset(50%);\n overflow: hidden;\n white-space: nowrap;\n}\n"],"mappings":""}
|
|
1
|
+
{"version":3,"file":"copyButton.module.mjs","names":[],"sources":["../../../../package/common/copyButton/copyButton.module.pcss"],"sourcesContent":["/* Pinned to a corner because the span has no root of its own to sit in: left at its static\n position, its containing block can be the page, and inside a scroll container that left\n empty page to scroll through below it. */\n.copyButton-status {\n position: absolute;\n top: 0;\n left: 0;\n width: 1px;\n height: 1px;\n padding: 0;\n border: 0;\n clip-path: inset(50%);\n overflow: hidden;\n white-space: nowrap;\n}\n"],"mappings":""}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"input.module.mjs","names":[],"sources":["../../../../package/common/input/input.module.pcss"],"sourcesContent":["/* Chrome fills a field on page load without firing anything React can see, and an animation\n bound to the pseudo-class is the only hook it offers. The declarations are inert on purpose;\n the pair exists to be listened for — see handleAutofillAnimation in input.tsx. */\n@keyframes inputAutofillStart {\n from {\n opacity: 1;\n }\n}\n\n@keyframes inputAutofillEnd {\n from {\n opacity: 1;\n }\n}\n\n.required-mark {\n padding: 0 0 0 4px;\n color: var(--required-mark-color, var(--error-color));\n}\n\n.input {\n position: relative;\n width: 100%;\n\n --input-notch-height: 1.75em;\n --input-icon-size: 1.2em;\n --input-icon-offset: 0.6em;\n --input-icon-gutter: 2.2em;\n\n /* The visible border lives on `fieldset`/`container` below, not this root — buried inside a\n `<label>`, out of reach of a plain ancestor selector. --group-radius-* are custom properties\n (not defined here) that a wrapping ButtonGroup sets per corner on the position it occupies;\n unlike border-radius itself they inherit through any nesting depth, so they reach these\n descendants and flatten the right corners when this Input sits inside a ButtonGroup. */\n --input-radius: var(--group-radius-tl, var(--default-border-radius))\n var(--group-radius-tr, var(--default-border-radius)) var(--group-radius-br, var(--default-border-radius))\n var(--group-radius-bl, var(--default-border-radius));\n\n &-placeholder {\n position: absolute;\n top: 50%;\n left: 7px;\n transform: translateY(-50%);\n transition: all 0.2s;\n opacity: 0;\n user-select: none;\n pointer-events: none;\n\n &-shown {\n animation: 0.2s fadeIn 0.3s forwards;\n }\n\n &-multiline {\n top: 14px;\n transform: translateY(0);\n }\n }\n\n &-matLabel {\n position: absolute;\n transition: all 0.3s;\n left: 7px;\n right: 0;\n top: 50%;\n transform: translateY(-50%);\n font-size: 1em;\n color: var(--input-label-resting-color, var(--text-light));\n pointer-events: none;\n user-select: none;\n\n &-floating {\n inset: 0 0 auto 14px;\n font-size: 0.8em;\n color: var(--input-label-floating-color, var(--text-color));\n transform: translateY(-50%);\n }\n\n &-multiline {\n top: 14px;\n transform: translateY(0);\n }\n }\n\n &-fieldset {\n position: absolute;\n width: 100%;\n margin: 0;\n padding: 0;\n min-width: 0;\n box-sizing: border-box;\n border-radius: var(--input-radius);\n font-size: 0.8em;\n inset: calc(var(--input-notch-height) / -2) 0 0;\n padding-left: 8px;\n border-width: 1px;\n border-style: solid;\n border-color: var(--border-color);\n pointer-events: none;\n user-select: none;\n\n &-legend {\n display: block;\n\n /* Not taken from the text: an empty span gets no line box, which raised a label-less\n field's border half a notch. */\n height: var(--input-notch-height);\n max-width: 0;\n transition: max-width 0.2s;\n white-space: nowrap;\n padding: 0;\n\n &-active {\n max-width: 300px;\n }\n\n span {\n line-height: var(--input-notch-height);\n padding: 0 5px;\n opacity: 0;\n }\n\n span:empty {\n padding: 0;\n }\n }\n }\n\n &-iconLeft {\n .input-matLabel {\n left: var(--input-icon-gutter);\n\n &-floating {\n left: calc(var(--input-icon-gutter) + 0.5em);\n }\n }\n\n .input-placeholder {\n left: var(--input-icon-gutter);\n }\n\n .input-fieldset {\n padding-left: var(--input-icon-gutter);\n }\n }\n\n &-container {\n display: flex;\n align-items: center;\n border-radius: var(--input-radius);\n background-color: var(--input-background);\n transition: border-color;\n cursor: text;\n height: 100%;\n\n &-multiline {\n overflow: hidden;\n padding-top: 10px;\n align-items: flex-start;\n\n /* Matches the textarea's padding-top, so they sit on its first line. */\n .input-field-icon,\n .input-field-suffix {\n margin-top: 4px;\n }\n }\n\n /* Not on the textarea, whose grip would sit beside the icons. The textarea's\n align-self: stretch is what makes it follow. */\n &-resizable {\n resize: vertical;\n }\n\n /* On the container, not the field, so it reaches under the icons and the suffix too. */\n &-disabled {\n background-color: var(--disabled-input-color);\n }\n\n &-border {\n transition: border-color;\n background-color: var(--input-background);\n outline: none;\n\n &-focused {\n outline-color: var(--focus-border-color, var(--primary-color));\n border-color: var(--focus-border-color, var(--primary-color));\n }\n\n &-searchFocused {\n outline-color: var(--search-input-color);\n outline-width: 2px;\n border-color: var(--search-input-color);\n }\n\n &-invalid {\n outline-color: var(--error-border-color);\n border-color: var(--error-border-color);\n }\n\n &-invalid:hover {\n outline-color: var(--error-border-color);\n border-color: var(--error-border-color);\n }\n\n &-error {\n outline-color: var(--error-border-color);\n border-color: var(--error-border-color);\n }\n }\n }\n\n &-label {\n display: flex;\n color: var(--text-color);\n height: 100%;\n\n &-column {\n flex-direction: column;\n }\n\n &-text {\n margin-right: 5px;\n margin-bottom: 6px;\n display: flex;\n align-items: center;\n color: color(var(--border-color) lightness(40%));\n background-color: transparent;\n font-size: 12px;\n position: absolute;\n top: -15px;\n white-space: nowrap;\n }\n }\n\n &-upper-right-label {\n position: absolute;\n transform: translateY(calc(-100% - 1.5px));\n right: 8px;\n min-height: 12px;\n font-size: 12px;\n color: color(var(--border-color) lightness(40%));\n }\n\n &-field {\n appearance: none;\n -webkit-appearance: none;\n font-family: inherit;\n font-size: inherit;\n box-sizing: border-box;\n resize: none;\n width: 100%;\n border: none;\n border-radius: var(--default-border-radius);\n overflow: hidden;\n line-height: 1.25;\n color: var(--text-color);\n background: transparent;\n\n &:focus {\n outline: none;\n }\n\n &::placeholder {\n color: var(--text-light);\n }\n\n /* Chrome overrides `background` and `color` on an autofilled field outright. Clipping the\n background to the glyphs is what removes it: the page cannot win on colour, but it can\n say where a background paints, and -webkit-text-fill-color then beats the text colour.\n The field is transparent either way, so what shows through is whatever is really behind\n it — no surface has to declare itself, which an inset-shadow cover-up would have needed. */\n &:-webkit-autofill,\n &:-webkit-autofill:hover,\n &:-webkit-autofill:focus,\n &:-webkit-autofill:active {\n animation-name: inputAutofillStart;\n animation-duration: 1ms;\n -webkit-background-clip: text;\n background-clip: text;\n -webkit-text-fill-color: var(--text-color);\n caret-color: var(--text-color);\n }\n\n &:not(:-webkit-autofill) {\n animation-name: inputAutofillEnd;\n animation-duration: 1ms;\n }\n\n /* The browser's own search-cancel decoration doesn't match the theme — Search has its own\n themed clear icon (see isSearchCleared in input.tsx) that replaces it. */\n &::-webkit-search-cancel-button,\n &::-webkit-search-decoration {\n -webkit-appearance: none;\n appearance: none;\n display: none;\n }\n\n /* The left icon's margins carry the gap, so the text starts exactly at --input-icon-gutter,\n where the label, the placeholder and the notch are drawn. */\n &-withIcon-left {\n padding-left: 0 !important;\n }\n\n &-suffix {\n padding-right: 9px;\n }\n\n &-date {\n padding: 6px 9px;\n color-scheme: dark;\n\n svg {\n color: var(--input-icon-color);\n }\n }\n\n &-default {\n padding: 8px 7.5px 6px;\n }\n\n &[disabled] {\n color: var(--disabled-font-color);\n -webkit-text-fill-color: var(--disabled-font-color);\n opacity: 1;\n\n &::placeholder {\n color: var(--disabled-font-color);\n -webkit-text-fill-color: var(--disabled-font-color);\n }\n }\n\n &-readOnly {\n cursor: default;\n color: var(--text-dark);\n -webkit-text-fill-color: var(--text-dark);\n }\n\n &-uppercase {\n text-transform: uppercase;\n }\n\n &-multiline {\n align-self: stretch;\n overflow-y: auto;\n padding-top: 4px;\n min-height: 30px;\n\n &-autoResize {\n overflow: hidden;\n }\n }\n\n &-icon {\n appearance: none;\n -webkit-appearance: none;\n box-sizing: border-box;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n background-color: transparent;\n border: none;\n outline: none;\n flex: none;\n margin-right: var(--input-icon-offset);\n color: var(--input-icon-color);\n width: var(--input-icon-size) !important;\n height: var(--input-icon-size) !important;\n user-select: none;\n\n &:focus-visible {\n outline: 1px solid var(--focus-border-color, var(--primary-color));\n outline-offset: 2px;\n }\n\n &-left {\n margin-left: var(--input-icon-offset);\n margin-right: calc(var(--input-icon-gutter) - var(--input-icon-offset) - var(--input-icon-size));\n }\n\n &-notClickable {\n pointer-events: none;\n }\n\n &-clear {\n transition: 0.15s ease-out;\n transition-property: width, margin-right, opacity;\n\n &-hidden {\n width: 0 !important;\n margin-right: 0;\n opacity: 0;\n visibility: hidden;\n\n /* Only on the way out: visibility holds at visible until the fade has played. */\n transition-property: width, margin-right, opacity, visibility;\n }\n }\n }\n }\n\n &-error {\n height: 1em;\n padding-top: 3px;\n color: var(--error-font-color);\n font-size: 11px;\n }\n\n @keyframes fadeIn {\n from {\n opacity: 0;\n }\n\n to {\n opacity: 0.5;\n }\n }\n}\n\n/* The label's glide between resting and floating is the motion; it still moves, just instantly.\n The clear button keeps its fade, while the suffix beside it jumps instead of sliding. */\n@media (prefers-reduced-motion: reduce) {\n .input-matLabel,\n .input-placeholder {\n transition: none;\n }\n\n .input-field-icon-clear {\n transition-property: opacity, visibility;\n }\n}\n"],"mappings":""}
|
|
1
|
+
{"version":3,"file":"input.module.mjs","names":[],"sources":["../../../../package/common/input/input.module.pcss"],"sourcesContent":["/* Chrome fills a field on page load without firing anything React can see, and an animation\n bound to the pseudo-class is the only hook it offers. The declarations are inert on purpose;\n the pair exists to be listened for — see handleAutofillAnimation in input.tsx. */\n@keyframes inputAutofillStart {\n from {\n opacity: 1;\n }\n}\n\n@keyframes inputAutofillEnd {\n from {\n opacity: 1;\n }\n}\n\n.required-mark {\n padding: 0 0 0 4px;\n color: var(--required-mark-color, var(--error-color));\n}\n\n.input {\n position: relative;\n width: 100%;\n\n --input-notch-height: 1.75em;\n --input-icon-size: 1.2em;\n --input-icon-offset: 0.6em;\n --input-icon-gutter: 2.2em;\n\n /* Uneven so that capitals and digits look centred, which leaves the line box 1px low. Icons centre\n on the field like the glyphs do; text beside the value (suffix, placeholder, resting label)\n moves down by half the difference to share its baseline. */\n --input-padding-top: 8px;\n --input-padding-bottom: 6px;\n\n /* Where the text starts, and so where the placeholder and the resting label start too. */\n --input-padding-inline: 7.5px;\n\n /* The visible border lives on `fieldset`/`container` below, not this root — buried inside a\n `<label>`, out of reach of a plain ancestor selector. --group-radius-* are custom properties\n (not defined here) that a wrapping ButtonGroup sets per corner on the position it occupies;\n unlike border-radius itself they inherit through any nesting depth, so they reach these\n descendants and flatten the right corners when this Input sits inside a ButtonGroup. */\n --input-radius: var(--group-radius-tl, var(--default-border-radius))\n var(--group-radius-tr, var(--default-border-radius)) var(--group-radius-br, var(--default-border-radius))\n var(--group-radius-bl, var(--default-border-radius));\n\n &-placeholder {\n position: absolute;\n top: calc(50% + (var(--input-padding-top) - var(--input-padding-bottom)) / 2);\n left: var(--input-padding-inline);\n transform: translateY(-50%);\n transition: all 0.2s;\n opacity: 0;\n user-select: none;\n pointer-events: none;\n\n &-shown {\n animation: 0.2s fadeIn 0.3s forwards;\n }\n\n &-multiline {\n top: 14px;\n transform: translateY(0);\n }\n }\n\n &-matLabel {\n position: absolute;\n transition: all 0.3s;\n left: var(--input-padding-inline);\n right: 0;\n top: calc(50% + (var(--input-padding-top) - var(--input-padding-bottom)) / 2);\n transform: translateY(-50%);\n font-size: 1em;\n color: var(--input-label-resting-color, var(--text-light));\n pointer-events: none;\n user-select: none;\n\n &-floating {\n inset: 0 0 auto 14px;\n font-size: 0.8em;\n color: var(--input-label-floating-color, var(--text-color));\n transform: translateY(-50%);\n }\n\n &-multiline {\n top: 14px;\n transform: translateY(0);\n }\n }\n\n &-fieldset {\n position: absolute;\n width: 100%;\n margin: 0;\n padding: 0;\n min-width: 0;\n box-sizing: border-box;\n border-radius: var(--input-radius);\n font-size: 0.8em;\n inset: calc(var(--input-notch-height) / -2) 0 0;\n padding-left: 8px;\n border-width: 1px;\n border-style: solid;\n border-color: var(--border-color);\n pointer-events: none;\n user-select: none;\n\n &-legend {\n display: block;\n\n /* Not taken from the text: an empty span gets no line box, which raised a label-less\n field's border half a notch. */\n height: var(--input-notch-height);\n max-width: 0;\n transition: max-width 0.2s;\n white-space: nowrap;\n padding: 0;\n\n &-active {\n max-width: 300px;\n }\n\n span {\n line-height: var(--input-notch-height);\n padding: 0 5px;\n opacity: 0;\n }\n\n span:empty {\n padding: 0;\n }\n }\n }\n\n &-iconLeft {\n .input-matLabel {\n left: var(--input-icon-gutter);\n\n &-floating {\n left: calc(var(--input-icon-gutter) + 0.5em);\n }\n }\n\n .input-placeholder {\n left: var(--input-icon-gutter);\n }\n\n .input-fieldset {\n padding-left: var(--input-icon-gutter);\n }\n }\n\n &-container {\n display: flex;\n align-items: center;\n border-radius: var(--input-radius);\n background-color: var(--input-background);\n transition: border-color;\n cursor: text;\n height: 100%;\n\n &-multiline {\n overflow: hidden;\n padding-top: 10px;\n align-items: flex-start;\n\n /* Matches the textarea's padding-top, so they sit on its first line. */\n .input-field-icon,\n .input-field-suffix {\n margin-top: 4px;\n }\n }\n\n /* Not on the textarea, whose grip would sit beside the icons. The textarea's\n align-self: stretch is what makes it follow. */\n &-resizable {\n resize: vertical;\n }\n\n /* On the container, not the field, so it reaches under the icons and the suffix too. */\n &-disabled {\n background-color: var(--disabled-input-color);\n }\n\n &-border {\n transition: border-color;\n background-color: var(--input-background);\n outline: none;\n\n &-focused {\n outline-color: var(--focus-border-color, var(--primary-color));\n border-color: var(--focus-border-color, var(--primary-color));\n }\n\n &-searchFocused {\n outline-color: var(--search-input-color);\n outline-width: 2px;\n border-color: var(--search-input-color);\n }\n\n &-invalid {\n outline-color: var(--error-border-color);\n border-color: var(--error-border-color);\n }\n\n &-invalid:hover {\n outline-color: var(--error-border-color);\n border-color: var(--error-border-color);\n }\n\n &-error {\n outline-color: var(--error-border-color);\n border-color: var(--error-border-color);\n }\n }\n }\n\n &-label {\n display: flex;\n color: var(--text-color);\n height: 100%;\n\n &-column {\n flex-direction: column;\n }\n\n &-text {\n margin-right: 5px;\n margin-bottom: 6px;\n display: flex;\n align-items: center;\n color: color(var(--border-color) lightness(40%));\n background-color: transparent;\n font-size: 12px;\n position: absolute;\n top: -15px;\n white-space: nowrap;\n }\n }\n\n &-upper-right-label {\n position: absolute;\n transform: translateY(calc(-100% - 1.5px));\n right: 8px;\n min-height: 12px;\n font-size: 12px;\n color: color(var(--border-color) lightness(40%));\n }\n\n &-field {\n appearance: none;\n -webkit-appearance: none;\n font-family: inherit;\n font-size: inherit;\n box-sizing: border-box;\n resize: none;\n width: 100%;\n border: none;\n border-radius: var(--default-border-radius);\n overflow: hidden;\n line-height: 1.25;\n color: var(--text-color);\n background: transparent;\n\n &:focus {\n outline: none;\n }\n\n &::placeholder {\n color: var(--text-light);\n }\n\n /* Chrome overrides `background` and `color` on an autofilled field outright. Clipping the\n background to the glyphs is what removes it: the page cannot win on colour, but it can\n say where a background paints, and -webkit-text-fill-color then beats the text colour.\n The field is transparent either way, so what shows through is whatever is really behind\n it — no surface has to declare itself, which an inset-shadow cover-up would have needed. */\n &:-webkit-autofill,\n &:-webkit-autofill:hover,\n &:-webkit-autofill:focus,\n &:-webkit-autofill:active {\n animation-name: inputAutofillStart;\n animation-duration: 1ms;\n -webkit-background-clip: text;\n background-clip: text;\n -webkit-text-fill-color: var(--text-color);\n caret-color: var(--text-color);\n }\n\n &:not(:-webkit-autofill) {\n animation-name: inputAutofillEnd;\n animation-duration: 1ms;\n }\n\n /* The browser's own search-cancel decoration doesn't match the theme — Search has its own\n themed clear icon (see isSearchCleared in input.tsx) that replaces it. */\n &::-webkit-search-cancel-button,\n &::-webkit-search-decoration {\n -webkit-appearance: none;\n appearance: none;\n display: none;\n }\n\n /* The left icon's margins carry the gap, so the text starts exactly at --input-icon-gutter,\n where the label, the placeholder and the notch are drawn. */\n &-withIcon-left {\n padding-left: 0 !important;\n }\n\n &-suffix {\n margin-top: calc(var(--input-padding-top) - var(--input-padding-bottom));\n padding-right: 9px;\n }\n\n &-date {\n padding: 6px 9px;\n color-scheme: dark;\n\n svg {\n color: var(--input-icon-color);\n }\n }\n\n &-default {\n padding: var(--input-padding-top) var(--input-padding-inline) var(--input-padding-bottom);\n }\n\n &[disabled] {\n color: var(--disabled-font-color);\n -webkit-text-fill-color: var(--disabled-font-color);\n opacity: 1;\n\n &::placeholder {\n color: var(--disabled-font-color);\n -webkit-text-fill-color: var(--disabled-font-color);\n }\n }\n\n &-readOnly {\n cursor: default;\n color: var(--text-dark);\n -webkit-text-fill-color: var(--text-dark);\n }\n\n &-uppercase {\n text-transform: uppercase;\n }\n\n &-multiline {\n align-self: stretch;\n overflow-y: auto;\n padding-top: 4px;\n min-height: 30px;\n\n &-autoResize {\n overflow: hidden;\n }\n }\n\n &-icon {\n appearance: none;\n -webkit-appearance: none;\n box-sizing: border-box;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n background-color: transparent;\n border: none;\n outline: none;\n flex: none;\n margin-right: var(--input-icon-offset);\n color: var(--input-icon-color);\n width: var(--input-icon-size) !important;\n height: var(--input-icon-size) !important;\n user-select: none;\n\n &:focus-visible {\n outline: 1px solid var(--focus-border-color, var(--primary-color));\n outline-offset: 2px;\n }\n\n &-left {\n margin-left: var(--input-icon-offset);\n margin-right: calc(var(--input-icon-gutter) - var(--input-icon-offset) - var(--input-icon-size));\n }\n\n &-notClickable {\n pointer-events: none;\n }\n\n &-clear {\n transition: 0.15s ease-out;\n transition-property: width, margin-right, opacity;\n\n &-hidden {\n width: 0 !important;\n margin-right: 0;\n opacity: 0;\n visibility: hidden;\n\n /* Only on the way out: visibility holds at visible until the fade has played. */\n transition-property: width, margin-right, opacity, visibility;\n }\n }\n }\n }\n\n &-error {\n height: 1em;\n padding-top: 3px;\n color: var(--error-font-color);\n font-size: 11px;\n }\n\n @keyframes fadeIn {\n from {\n opacity: 0;\n }\n\n to {\n opacity: 0.5;\n }\n }\n}\n\n/* The label's glide between resting and floating is the motion; it still moves, just instantly.\n The clear button keeps its fade, while the suffix beside it jumps instead of sliding. */\n@media (prefers-reduced-motion: reduce) {\n .input-matLabel,\n .input-placeholder {\n transition: none;\n }\n\n .input-field-icon-clear {\n transition-property: opacity, visibility;\n }\n}\n"],"mappings":""}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use client";var e=`numberInput-split_1kFLr`,t=`
|
|
1
|
+
"use client";var e=`numberInput-split_1kFLr`,t=`numberInput_7p2O3`,n=`arrowSuffix_QECPG`,r=`arrows_yjRlc`,i=`arrowBtn_DbJoa`,a=`split_FYvfQ`,o=`splitBtn_MquuB`,s=`split-invalid_F94dA`,c={"numberInput-split":`numberInput-split_1kFLr`,numberInputSplit:e,numberInput:t,arrowSuffix:n,arrows:r,arrowBtn:i,split:a,splitBtn:o,"split-invalid":`split-invalid_F94dA`,splitInvalid:s};export{i as arrowBtn,n as arrowSuffix,r as arrows,c as default,t as numberInput,e as numberInputSplit,a as split,o as splitBtn,s as splitInvalid};
|
|
2
2
|
//# sourceMappingURL=numberInput.module.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"numberInput.module.mjs","names":[],"sources":["../../../../package/common/numberInput/numberInput.module.pcss"],"sourcesContent":[".numberInput {\n /* Only set when the split layout wraps this input in a flex row. */\n &-split {\n flex: 1;\n min-width: 0;\n }\n}\n\n/* ── Stacked layout: chevrons inside the field's right edge (mouse-oriented) ───────── */\n\n/* Input's `suffix` slot: stretch to the field so the chevrons get its full height. */\n.arrowSuffix {\n align-self: stretch;\n display: flex;\n padding-right: 0;\n}\n\n.arrows {\n display: flex;\n flex-direction: column;\n align-self: stretch;\n border-left: 1px solid var(--border-color);\n\n /* Sitting flush against the field's edge, the chevrons' background would square off its\n rounded corner, so it is clipped. Read from --group-radius-* like Input's own border, so it\n still flattens inside a ButtonGroup. */\n overflow: hidden;\n border-top-right-radius: var(--group-radius-tr, var(--default-border-radius));\n border-bottom-right-radius: var(--group-radius-br, var(--default-border-radius));\n}\n\n.arrowBtn {\n flex: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n background: none;\n border: none;\n padding: 0 0.5em;\n\n /* No min-height: the two halves divide the field's own height, so a stepper never makes a\n NumberInput taller than a plain Input. In em, so it tracks the field's text size. */\n min-width: 1.75em;\n font-size: 0.75em;\n line-height: 1;\n color: var(--text-dark);\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n\n /* So a long press reads as a hold, not a text gesture. */\n touch-action: manipulation;\n user-select: none;\n -webkit-user-select: none;\n -webkit-touch-callout: none;\n transition:\n color 0.15s,\n opacity 0.15s;\n\n &:disabled {\n cursor: default;\n opacity: 0.35;\n }\n\n &:focus-visible {\n outline: 2px solid var(--focus-border-color, var(--primary-color));\n outline-offset: -2px;\n }\n\n /* (hover: hover) only — on touch a :hover state latches after a tap until you tap elsewhere.\n\n Colour-only, unlike the --background-accent-light hover surface used elsewhere in the\n library: this button sits flush against .arrows' 1px --border-color divider, and in dark\n palettes those two tokens are close enough in luminance that painting the surface right up\n to the line eats most of the divider's already-low contrast, under the pointer. Tuning the\n hover colour per theme would not hold — the collision is between three tokens (divider,\n hover surface, field background), so any new theme can reintroduce it. The chevron turning\n --primary-color is affordance enough on a target this small. */\n @media (hover: hover) {\n &:hover:not(:disabled) {\n color: var(--primary-color);\n }\n }\n\n &:active:not(:disabled) {\n color: var(--primary-color);\n }\n}\n\n/* ── Split layout: full-height − / + flanking the field (touch-oriented) ───────────── */\n\n/* ButtonGroup is inline-flex; a form field fills its row instead, with the Input taking the\n slack (see .numberInput-split). The class is repeated to beat `.buttonGroup`'s own `display`\n without depending on which CSS module the bundler emits first. */\n.split.split {\n display: flex;\n width: 100%;\n}\n\n/* Two classes, to outrank Button's one-class rules whichever stylesheet loads first. Resting state\n only: Button's hover and press layer tints over it. */\n.split .splitBtn {\n background: var(--input-background);\n color: var(--text-dark);\n border-color: var(--border-color);\n}\n\n.splitBtn {\n flex: 0 0 auto;\n\n /* No fixed height — ButtonGroup stretches these to the field.\n\n The width repeats Input's own height formula (`line-height: 1.25` plus the 8px/6px padding\n of `.input-field-default`) to come out square at any text size, and must follow it if that\n padding changes. `aspect-ratio: 1` cannot do this: a flex item's main size is resolved from\n its content before the stretched cross size exists. */\n align-self: stretch;\n width: calc(1.25em + 14px);\n touch-action: manipulation;\n user-select: none;\n -webkit-user-select: none;\n -webkit-touch-callout: none;\n transition: opacity 0.15s;\n\n &:disabled {\n opacity: 0.35;\n }\n\n &:focus-visible {\n outline: 2px solid var(--focus-border-color, var(--primary-color));\n outline-offset: 2px;\n }\n}\n\n/* One continuous border, so the buttons follow the field's focus and error colours — left grey,\n the group reads as a box inside a box. */\n.split:focus-within .splitBtn {\n border-color: var(--focus-border-color, var(--primary-color));\n}\n\n.split-invalid .splitBtn {\n border-color: var(--error-border-color);\n}\n"],"mappings":""}
|
|
1
|
+
{"version":3,"file":"numberInput.module.mjs","names":[],"sources":["../../../../package/common/numberInput/numberInput.module.pcss"],"sourcesContent":[".numberInput {\n /* Only set when the split layout wraps this input in a flex row. */\n &-split {\n flex: 1;\n min-width: 0;\n }\n}\n\n/* ── Stacked layout: chevrons inside the field's right edge (mouse-oriented) ───────── */\n\n/* Input's `suffix` slot: stretch to the field so the chevrons get its full height. Two classes, to\n outrank Input's one-class suffix rules whichever stylesheet loads first. */\n.numberInput .arrowSuffix {\n align-self: stretch;\n display: flex;\n padding-right: 0;\n margin-top: 0;\n}\n\n.arrows {\n display: flex;\n flex-direction: column;\n align-self: stretch;\n border-left: 1px solid var(--border-color);\n\n /* Sitting flush against the field's edge, the chevrons' background would square off its\n rounded corner, so it is clipped. Read from --group-radius-* like Input's own border, so it\n still flattens inside a ButtonGroup. */\n overflow: hidden;\n border-top-right-radius: var(--group-radius-tr, var(--default-border-radius));\n border-bottom-right-radius: var(--group-radius-br, var(--default-border-radius));\n}\n\n.arrowBtn {\n flex: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n background: none;\n border: none;\n padding: 0 0.5em;\n\n /* No min-height: the two halves divide the field's own height, so a stepper never makes a\n NumberInput taller than a plain Input. In em, so it tracks the field's text size. */\n min-width: 1.75em;\n font-size: 0.75em;\n line-height: 1;\n color: var(--text-dark);\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n\n /* So a long press reads as a hold, not a text gesture. */\n touch-action: manipulation;\n user-select: none;\n -webkit-user-select: none;\n -webkit-touch-callout: none;\n transition:\n color 0.15s,\n opacity 0.15s;\n\n &:disabled {\n cursor: default;\n opacity: 0.35;\n }\n\n &:focus-visible {\n outline: 2px solid var(--focus-border-color, var(--primary-color));\n outline-offset: -2px;\n }\n\n /* (hover: hover) only — on touch a :hover state latches after a tap until you tap elsewhere.\n\n Colour-only, unlike the --background-accent-light hover surface used elsewhere in the\n library: this button sits flush against .arrows' 1px --border-color divider, and in dark\n palettes those two tokens are close enough in luminance that painting the surface right up\n to the line eats most of the divider's already-low contrast, under the pointer. Tuning the\n hover colour per theme would not hold — the collision is between three tokens (divider,\n hover surface, field background), so any new theme can reintroduce it. The chevron turning\n --primary-color is affordance enough on a target this small. */\n @media (hover: hover) {\n &:hover:not(:disabled) {\n color: var(--primary-color);\n }\n }\n\n &:active:not(:disabled) {\n color: var(--primary-color);\n }\n}\n\n/* ── Split layout: full-height − / + flanking the field (touch-oriented) ───────────── */\n\n/* ButtonGroup is inline-flex; a form field fills its row instead, with the Input taking the\n slack (see .numberInput-split). The class is repeated to beat `.buttonGroup`'s own `display`\n without depending on which CSS module the bundler emits first. */\n.split.split {\n display: flex;\n width: 100%;\n}\n\n/* Two classes, to outrank Button's one-class rules whichever stylesheet loads first. Resting state\n only: Button's hover and press layer tints over it. */\n.split .splitBtn {\n background: var(--input-background);\n color: var(--text-dark);\n border-color: var(--border-color);\n}\n\n.splitBtn {\n flex: 0 0 auto;\n\n /* No fixed height — ButtonGroup stretches these to the field.\n\n The width repeats Input's own height formula (`line-height: 1.25` plus the 8px/6px padding\n of `.input-field-default`) to come out square at any text size, and must follow it if that\n padding changes. `aspect-ratio: 1` cannot do this: a flex item's main size is resolved from\n its content before the stretched cross size exists. */\n align-self: stretch;\n width: calc(1.25em + 14px);\n touch-action: manipulation;\n user-select: none;\n -webkit-user-select: none;\n -webkit-touch-callout: none;\n transition: opacity 0.15s;\n\n &:disabled {\n opacity: 0.35;\n }\n\n &:focus-visible {\n outline: 2px solid var(--focus-border-color, var(--primary-color));\n outline-offset: 2px;\n }\n}\n\n/* One continuous border, so the buttons follow the field's focus and error colours — left grey,\n the group reads as a box inside a box. */\n.split:focus-within .splitBtn {\n border-color: var(--focus-border-color, var(--primary-color));\n}\n\n.split-invalid .splitBtn {\n border-color: var(--error-border-color);\n}\n"],"mappings":""}
|