@sigx/zero-daisyui 0.11.0 → 0.13.0
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/README.md +5 -0
- package/dist/css/components/combobox.css +2 -1
- package/dist/css/components/radio-group.css +6 -0
- package/dist/css/index.css +8 -1
- package/dist/lynx/components/checkbox.css +44 -11
- package/dist/lynx/components/combobox.css +2 -1
- package/dist/lynx/components/fieldset.css +10 -1
- package/dist/lynx/components/input.css +40 -2
- package/dist/lynx/components/number-input.css +38 -3
- package/dist/lynx/components/radio-group.css +10 -3
- package/dist/lynx/components/textarea.css +31 -7
- package/dist/lynx/components/toast.css +0 -8
- package/dist/lynx/components/toggle-group.css +54 -2
- package/dist/lynx/components/toggle.css +27 -2
- package/dist/lynx/index.css +256 -46
- package/dist/lynx/manifest.json +3 -3
- package/dist/lynx/tokens.css +0 -6
- package/dist/manifest.json +1 -1
- package/dist/recipes.d.ts.map +1 -1
- package/dist/recipes.js +435 -23
- package/dist/recipes.js.map +1 -1
- package/dist/report.json +73 -13
- package/package.json +4 -4
- package/src/recipes.ts +440 -23
package/dist/lynx/tokens.css
CHANGED
|
@@ -86,7 +86,6 @@
|
|
|
86
86
|
--depth-shade: #0000001a;
|
|
87
87
|
--depth-sheen: #ffffff1a;
|
|
88
88
|
--noise: 0;
|
|
89
|
-
--fx-noise: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 200'%3E%3Cfilter id='a'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='1.34' numOctaves='4' stitchTiles='stitch'%3E%3C/feTurbulence%3E%3C/filter%3E%3Crect width='200' height='200' filter='url(%23a)' opacity='0.2'%3E%3C/rect%3E%3C/svg%3E");
|
|
90
89
|
}
|
|
91
90
|
|
|
92
91
|
.zx-root.zx-theme-light {
|
|
@@ -163,7 +162,6 @@
|
|
|
163
162
|
--depth-shade: #0000001a;
|
|
164
163
|
--depth-sheen: #ffffff1a;
|
|
165
164
|
--noise: 0;
|
|
166
|
-
--fx-noise: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 200'%3E%3Cfilter id='a'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='1.34' numOctaves='4' stitchTiles='stitch'%3E%3C/feTurbulence%3E%3C/filter%3E%3Crect width='200' height='200' filter='url(%23a)' opacity='0.2'%3E%3C/rect%3E%3C/svg%3E");
|
|
167
165
|
}
|
|
168
166
|
|
|
169
167
|
.zx-root.zx-theme-dark {
|
|
@@ -240,7 +238,6 @@
|
|
|
240
238
|
--depth-shade: #0000001a;
|
|
241
239
|
--depth-sheen: #ffffff1a;
|
|
242
240
|
--noise: 0;
|
|
243
|
-
--fx-noise: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 200'%3E%3Cfilter id='a'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='1.34' numOctaves='4' stitchTiles='stitch'%3E%3C/feTurbulence%3E%3C/filter%3E%3Crect width='200' height='200' filter='url(%23a)' opacity='0.2'%3E%3C/rect%3E%3C/svg%3E");
|
|
244
241
|
}
|
|
245
242
|
|
|
246
243
|
.zx-root.zx-theme-dim {
|
|
@@ -317,7 +314,6 @@
|
|
|
317
314
|
--depth-shade: #00000000;
|
|
318
315
|
--depth-sheen: #ffffff00;
|
|
319
316
|
--noise: 0;
|
|
320
|
-
--fx-noise: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 200'%3E%3Cfilter id='a'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='1.34' numOctaves='4' stitchTiles='stitch'%3E%3C/feTurbulence%3E%3C/filter%3E%3Crect width='200' height='200' filter='url(%23a)' opacity='0.2'%3E%3C/rect%3E%3C/svg%3E");
|
|
321
317
|
}
|
|
322
318
|
|
|
323
319
|
.zx-root.zx-theme-nord {
|
|
@@ -394,7 +390,6 @@
|
|
|
394
390
|
--depth-shade: #00000000;
|
|
395
391
|
--depth-sheen: #ffffff00;
|
|
396
392
|
--noise: 0;
|
|
397
|
-
--fx-noise: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 200'%3E%3Cfilter id='a'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='1.34' numOctaves='4' stitchTiles='stitch'%3E%3C/feTurbulence%3E%3C/filter%3E%3Crect width='200' height='200' filter='url(%23a)' opacity='0.2'%3E%3C/rect%3E%3C/svg%3E");
|
|
398
393
|
}
|
|
399
394
|
|
|
400
395
|
.zx-root.zx-theme-sunset {
|
|
@@ -471,5 +466,4 @@
|
|
|
471
466
|
--depth-shade: #00000000;
|
|
472
467
|
--depth-sheen: #ffffff00;
|
|
473
468
|
--noise: 0;
|
|
474
|
-
--fx-noise: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 200'%3E%3Cfilter id='a'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='1.34' numOctaves='4' stitchTiles='stitch'%3E%3C/feTurbulence%3E%3C/filter%3E%3Crect width='200' height='200' filter='url(%23a)' opacity='0.2'%3E%3C/rect%3E%3C/svg%3E");
|
|
475
469
|
}
|
package/dist/manifest.json
CHANGED
package/dist/recipes.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"recipes.d.ts","sourceRoot":"","sources":["../src/recipes.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAwB,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAmQxE;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,eAAO,MAAM,IAAI,EAAE,WAqVlB,CAAC;AA4BF,eAAO,MAAM,WAAW,EAAE,WA+EzB,CAAC;AAGF,eAAO,MAAM,YAAY,EAAE,WA0R1B,CAAC;AAmJF,eAAO,MAAM,MAAM,EAAE,WA0GpB,CAAC;AA4CF,eAAO,MAAM,OAAO,EAAE,WAoDrB,CAAC;AAEF,eAAO,MAAM,OAAO,EAAE,WA0CrB,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,SAAS,EAAE,WAyCvB,CAAC;AAGF,eAAO,MAAM,IAAI,EAAE,WAsKlB,CAAC;AAIF,eAAO,MAAM,OAAO,EAAE,WAmCrB,CAAC;AAEF,eAAO,MAAM,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"recipes.d.ts","sourceRoot":"","sources":["../src/recipes.ts"],"names":[],"mappings":"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"}
|
package/dist/recipes.js
CHANGED
|
@@ -1621,6 +1621,10 @@ export const field = {
|
|
|
1621
1621
|
label: {
|
|
1622
1622
|
base: { fontSize: 'var(--text-sm)', fontWeight: 'var(--weight-semibold)', color: 'var(--field-accent)' },
|
|
1623
1623
|
states: { disabled: { opacity: 'var(--disabled-opacity)' } },
|
|
1624
|
+
// lynx has no pseudo-elements and the anatomy no part to carry
|
|
1625
|
+
// the asterisk, so it stays a web-only mark: on lynx a required
|
|
1626
|
+
// field still stamps `required` on its root and label, and the
|
|
1627
|
+
// control inside adopts it (signalxjs/lynx#1205).
|
|
1624
1628
|
selectors: {
|
|
1625
1629
|
'&[data-required]::after': { content: '" *"', color: roleInk('error') },
|
|
1626
1630
|
},
|
|
@@ -1711,6 +1715,33 @@ export const fieldset = {
|
|
|
1711
1715
|
xl: { legend: { base: { fontSize: 'var(--text-lg)' } } },
|
|
1712
1716
|
},
|
|
1713
1717
|
},
|
|
1718
|
+
// Lynx has no grid: the one-column track becomes a flex column (the gap
|
|
1719
|
+
// survives), and the block/inline paddings are restated physically —
|
|
1720
|
+
// logical spellings resolve on iOS but not on Android (signalxjs/lynx#1084).
|
|
1721
|
+
targets: {
|
|
1722
|
+
lynx: {
|
|
1723
|
+
parts: {
|
|
1724
|
+
root: {
|
|
1725
|
+
base: {
|
|
1726
|
+
display: 'flex',
|
|
1727
|
+
flexDirection: 'column',
|
|
1728
|
+
paddingTop: 'var(--space-xs)',
|
|
1729
|
+
paddingBottom: 'var(--space-xs)',
|
|
1730
|
+
paddingLeft: '0',
|
|
1731
|
+
paddingRight: '0',
|
|
1732
|
+
},
|
|
1733
|
+
},
|
|
1734
|
+
legend: {
|
|
1735
|
+
base: {
|
|
1736
|
+
paddingTop: 'var(--space-sm)',
|
|
1737
|
+
paddingBottom: 'var(--space-sm)',
|
|
1738
|
+
paddingLeft: '0',
|
|
1739
|
+
paddingRight: '0',
|
|
1740
|
+
},
|
|
1741
|
+
},
|
|
1742
|
+
},
|
|
1743
|
+
},
|
|
1744
|
+
},
|
|
1714
1745
|
};
|
|
1715
1746
|
/**
|
|
1716
1747
|
* daisy's tick, drawn by a clip-path that GROWS.
|
|
@@ -1723,6 +1754,12 @@ export const fieldset = {
|
|
|
1723
1754
|
* horizontal bar and lifts it to the middle. All three verbatim from daisyUI
|
|
1724
1755
|
* 5.7.8's `.checkbox:before` / `:checked` / `:indeterminate`.
|
|
1725
1756
|
*/
|
|
1757
|
+
/**
|
|
1758
|
+
* The lynx tick's stroke: 20% of the checkbox's content box — the width of
|
|
1759
|
+
* daisy's polygon bars — as a length, since borders take no percentage.
|
|
1760
|
+
* The content box is the control less its padding and border on both sides.
|
|
1761
|
+
*/
|
|
1762
|
+
const CHECKBOX_LYNX_STROKE = 'calc((var(--checkbox-size) - var(--checkbox-pad) * 2 - var(--border) * 2) * 0.2)';
|
|
1726
1763
|
const TICK_COLLAPSED = 'polygon(20% 100%, 20% 80%, 50% 80%, 50% 80%, 70% 80%, 70% 100%)';
|
|
1727
1764
|
const TICK_DRAWN = 'polygon(20% 100%, 20% 80%, 50% 80%, 50% 0%, 70% 0%, 70% 100%)';
|
|
1728
1765
|
const DASH_DRAWN = 'polygon(20% 100%, 20% 80%, 50% 80%, 50% 80%, 80% 80%, 80% 100%)';
|
|
@@ -1939,33 +1976,83 @@ export const checkbox = {
|
|
|
1939
1976
|
targets: {
|
|
1940
1977
|
lynx: {
|
|
1941
1978
|
parts: {
|
|
1979
|
+
// The box/label row, pinned: `inline-flex` is rewritten to
|
|
1980
|
+
// `flex`, and the row must not depend on the engine's
|
|
1981
|
+
// default direction (signalxjs/lynx#1203).
|
|
1982
|
+
root: { base: { display: 'flex', flexDirection: 'row' } },
|
|
1942
1983
|
control: {
|
|
1943
1984
|
// The web fallback (`color-mix(in oklab, … currentColor …)`)
|
|
1944
1985
|
// exists for consumers that unset the accent; this package
|
|
1945
1986
|
// always defines it, so the plain accent IS the ring.
|
|
1946
|
-
|
|
1987
|
+
//
|
|
1988
|
+
// `inline-block` is not a lynx display value (no inline
|
|
1989
|
+
// formatting context); a flex box keeps daisy's geometry —
|
|
1990
|
+
// the padding insets the 100%-sized indicator either way.
|
|
1991
|
+
base: { display: 'flex', border: 'var(--border) solid var(--checkbox-accent)' },
|
|
1992
|
+
// The ring as spread shadows that follow the box's radius
|
|
1993
|
+
// (signalxjs/lynx#1163 — lynx's `outline` ignores it and
|
|
1994
|
+
// has no offset), keeping the box's inset depth line.
|
|
1995
|
+
states: {
|
|
1996
|
+
'focus-visible': lynxFocusRing('var(--checkbox-accent)', { under: '0 1px var(--depth-shade) inset' }),
|
|
1997
|
+
},
|
|
1947
1998
|
},
|
|
1948
1999
|
indicator: {
|
|
1949
|
-
// The tick
|
|
1950
|
-
//
|
|
1951
|
-
//
|
|
2000
|
+
// The tick WITHOUT clip-path, which lynx does not apply
|
|
2001
|
+
// (measured on iOS, signalxjs/lynx#1216 — daisy's
|
|
2002
|
+
// polygon-cut box drew as a solid diamond; the emitter
|
|
2003
|
+
// now drops every clip-path). daisy's drawn polygon is an
|
|
2004
|
+
// L inside the content box: a bar at x 50–70% over the
|
|
2005
|
+
// full height and a foot at y 80–100% from x 20%, both
|
|
2006
|
+
// 20% of the box thick, rotated 45° about the box's
|
|
2007
|
+
// centre. That is exactly the classic two-border check:
|
|
2008
|
+
// a 50%-wide full-height box at x 20% with a right and a
|
|
2009
|
+
// bottom border 20% of the content box thick, turned
|
|
2010
|
+
// about the content box's centre (60% 50% of itself).
|
|
2011
|
+
//
|
|
2012
|
+
// The ink: the control's `color:` names
|
|
2013
|
+
// `--checkbox-on-accent`, and `currentColor` was that ink
|
|
2014
|
+
// by inheritance (it never resolves on lynx,
|
|
2015
|
+
// signalxjs/lynx#1079) — spent directly on the borders.
|
|
1952
2016
|
//
|
|
1953
|
-
// The
|
|
1954
|
-
//
|
|
1955
|
-
//
|
|
1956
|
-
//
|
|
1957
|
-
// proven on both platforms — and the transition follows
|
|
1958
|
-
// the property that now moves.
|
|
2017
|
+
// The motion is `transform`: the standalone `rotate` /
|
|
2018
|
+
// `translate` properties resolve on iOS but not on
|
|
2019
|
+
// Android (signalxjs/lynx#1084). No sheen shadow — on a
|
|
2020
|
+
// hollow box it would band the inside of the L.
|
|
1959
2021
|
base: {
|
|
1960
|
-
|
|
2022
|
+
boxSizing: 'border-box',
|
|
2023
|
+
width: '50%',
|
|
2024
|
+
height: '100%',
|
|
2025
|
+
marginLeft: '20%',
|
|
2026
|
+
backgroundColor: 'transparent',
|
|
2027
|
+
borderStyle: 'solid',
|
|
2028
|
+
borderColor: 'var(--checkbox-on-accent)',
|
|
2029
|
+
borderTopWidth: '0',
|
|
2030
|
+
borderLeftWidth: '0',
|
|
2031
|
+
borderRightWidth: CHECKBOX_LYNX_STROKE,
|
|
2032
|
+
borderBottomWidth: CHECKBOX_LYNX_STROKE,
|
|
2033
|
+
boxShadow: 'none',
|
|
2034
|
+
transformOrigin: '60% 50%',
|
|
1961
2035
|
transform: 'rotate(45deg)',
|
|
1962
|
-
transition: '
|
|
1963
|
-
+ 'opacity var(--duration-instant) var(--ease-standard) var(--duration-instant), '
|
|
2036
|
+
transition: 'opacity var(--duration-instant) var(--ease-standard) var(--duration-instant), '
|
|
1964
2037
|
+ 'transform var(--duration-slow) var(--ease-standard) var(--duration-instant)',
|
|
1965
2038
|
},
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
2039
|
+
states: {
|
|
2040
|
+
// daisy's dash (signalxjs/lynx#1217): the same six
|
|
2041
|
+
// points un-rotated into a bar at x 20–80%, 20% of
|
|
2042
|
+
// the box tall, lifted to the middle. Here a filled,
|
|
2043
|
+
// borderless 60% × 20% box centred on the cross
|
|
2044
|
+
// axis — the unclipped full-height box had painted
|
|
2045
|
+
// the top half of the control.
|
|
2046
|
+
indeterminate: {
|
|
2047
|
+
width: '60%',
|
|
2048
|
+
height: '20%',
|
|
2049
|
+
alignSelf: 'center',
|
|
2050
|
+
borderRightWidth: '0',
|
|
2051
|
+
borderBottomWidth: '0',
|
|
2052
|
+
backgroundColor: 'var(--checkbox-on-accent)',
|
|
2053
|
+
transform: 'rotate(0deg)',
|
|
2054
|
+
},
|
|
2055
|
+
},
|
|
1969
2056
|
},
|
|
1970
2057
|
},
|
|
1971
2058
|
},
|
|
@@ -1989,6 +2076,11 @@ export const radioGroup = {
|
|
|
1989
2076
|
// `invalid` paints on each `item-control`, which carries the flag
|
|
1990
2077
|
// itself (#267) — the root only groups the items.
|
|
1991
2078
|
states: { invalid: {}, required: {} },
|
|
2079
|
+
// `orientation="horizontal"` lays the items in a wrapping row —
|
|
2080
|
+
// checkbox-group's rule (signalxjs/zero#393).
|
|
2081
|
+
selectors: {
|
|
2082
|
+
'&[data-orientation="horizontal"]': { flexDirection: 'row', flexWrap: 'wrap', columnGap: 'var(--space-lg)' },
|
|
2083
|
+
},
|
|
1992
2084
|
},
|
|
1993
2085
|
label: {
|
|
1994
2086
|
base: { fontSize: 'var(--text-sm)', fontWeight: 'var(--weight-semibold)' },
|
|
@@ -2096,9 +2188,20 @@ export const radioGroup = {
|
|
|
2096
2188
|
targets: {
|
|
2097
2189
|
lynx: {
|
|
2098
2190
|
parts: {
|
|
2191
|
+
// The control/label row, pinned — as checkbox's root
|
|
2192
|
+
// (signalxjs/lynx#1203).
|
|
2193
|
+
item: { base: { display: 'flex', flexDirection: 'row' } },
|
|
2099
2194
|
'item-control': {
|
|
2100
|
-
|
|
2101
|
-
|
|
2195
|
+
// `display: flex` in place of `inline-block`, which lynx
|
|
2196
|
+
// does not have — the padding still insets the dot.
|
|
2197
|
+
base: { display: 'flex', border: 'var(--border) solid var(--radio-accent)' },
|
|
2198
|
+
states: {
|
|
2199
|
+
checked: { borderColor: 'var(--radio-accent)' },
|
|
2200
|
+
// The round ring (signalxjs/lynx#1163): spread
|
|
2201
|
+
// shadows follow the 9999px radius where `outline`
|
|
2202
|
+
// drew a square.
|
|
2203
|
+
'focus-visible': lynxFocusRing('var(--radio-accent)', { under: '0 1px var(--depth-shade) inset' }),
|
|
2204
|
+
},
|
|
2102
2205
|
},
|
|
2103
2206
|
'item-indicator': {
|
|
2104
2207
|
states: { checked: { backgroundColor: 'var(--radio-accent)' } },
|
|
@@ -3984,6 +4087,11 @@ export const combobox = {
|
|
|
3984
4087
|
flexWrap: 'wrap',
|
|
3985
4088
|
minWidth: '13rem',
|
|
3986
4089
|
...fieldControl,
|
|
4090
|
+
// The one field control that wraps: under `multiple` its tags
|
|
4091
|
+
// flow onto new rows, so the field step is a floor, not a cap —
|
|
4092
|
+
// a fixed height spills wrapped tags over the next field (#407).
|
|
4093
|
+
height: 'auto',
|
|
4094
|
+
minHeight: fieldHeight('md'),
|
|
3987
4095
|
transition: 'border-color var(--duration-fast) var(--ease-standard)',
|
|
3988
4096
|
},
|
|
3989
4097
|
states: {
|
|
@@ -4287,7 +4395,50 @@ export const toggle = {
|
|
|
4287
4395
|
},
|
|
4288
4396
|
},
|
|
4289
4397
|
defaultVariants: { color: 'primary', size: 'md' },
|
|
4398
|
+
// signalxjs/lynx#1204 — the lynx replacements for what this recipe's
|
|
4399
|
+
// shared sections cannot say there.
|
|
4400
|
+
targets: {
|
|
4401
|
+
lynx: {
|
|
4402
|
+
parts: {
|
|
4403
|
+
root: {
|
|
4404
|
+
// daisy's content-sized, never-squeezed btn (lynx#1165):
|
|
4405
|
+
// a lynx view has no inline formatting context, so the
|
|
4406
|
+
// toggle stretched to its column and a squeezed label
|
|
4407
|
+
// wrapped per character. The glyph + label sit in a row.
|
|
4408
|
+
// The hairline as longhands: a var-bearing `border`
|
|
4409
|
+
// shorthand expands after the cascade and would beat
|
|
4410
|
+
// any edge a later rule restates (lynx#1161/#1162).
|
|
4411
|
+
base: {
|
|
4412
|
+
...lynxBtnFit,
|
|
4413
|
+
flexDirection: 'row',
|
|
4414
|
+
border: '0 solid transparent',
|
|
4415
|
+
...lynxSides('border{}Width', 'var(--border)'),
|
|
4416
|
+
...lynxSides('border{}Color', 'var(--color-base-300)'),
|
|
4417
|
+
},
|
|
4418
|
+
states: {
|
|
4419
|
+
// No hover on a touch platform: the held toggle
|
|
4420
|
+
// takes the wash daisy's hover gives it. The shared
|
|
4421
|
+
// pressed rule adds the btn's 1px sink.
|
|
4422
|
+
pressed: { background: 'var(--color-base-300)' },
|
|
4423
|
+
on: lynxSides('border{}Color', 'var(--toggle-accent)'),
|
|
4424
|
+
// lynx's `outline` ignores the radius and has no
|
|
4425
|
+
// offset (lynx#1163): the ring as spread shadows.
|
|
4426
|
+
'focus-visible': lynxFocusRing('var(--toggle-accent)'),
|
|
4427
|
+
},
|
|
4428
|
+
selectors: {
|
|
4429
|
+
// A held on toggle keeps its fill (the web's
|
|
4430
|
+
// `[data-state=on]:hover` stays on the accent too).
|
|
4431
|
+
'&[data-state="on"][data-pressed]': { background: 'var(--toggle-accent)' },
|
|
4432
|
+
},
|
|
4433
|
+
},
|
|
4434
|
+
},
|
|
4435
|
+
},
|
|
4436
|
+
},
|
|
4290
4437
|
};
|
|
4438
|
+
/** A toggle-group end item's outer corner: the frame's radius inside its hairline. */
|
|
4439
|
+
const joinInnerRadius = 'calc(var(--radius-field) - var(--border))';
|
|
4440
|
+
/** A zero seam width that still holds var(), so it can beat the var-bearing seam on lynx. */
|
|
4441
|
+
const noSeam = 'calc(var(--border) * 0)';
|
|
4291
4442
|
// daisy "join" of btns: one bordered capsule, hairline seams between items,
|
|
4292
4443
|
// the on item filled with the accent.
|
|
4293
4444
|
export const toggleGroup = {
|
|
@@ -4395,6 +4546,101 @@ export const toggleGroup = {
|
|
|
4395
4546
|
])),
|
|
4396
4547
|
},
|
|
4397
4548
|
defaultVariants: { color: 'primary' },
|
|
4549
|
+
// signalxjs/lynx#1204 — the lynx replacements for what this recipe's
|
|
4550
|
+
// shared sections cannot say there.
|
|
4551
|
+
targets: {
|
|
4552
|
+
lynx: {
|
|
4553
|
+
parts: {
|
|
4554
|
+
root: {
|
|
4555
|
+
// Content-sized like the web's inline-flex capsule (a
|
|
4556
|
+
// lynx view stretches to its column otherwise), a row
|
|
4557
|
+
// unless vertical, and the frame as longhands so the
|
|
4558
|
+
// orientation rules below can drop one edge by
|
|
4559
|
+
// specificity (a var-bearing `border` shorthand would
|
|
4560
|
+
// expand over them, lynx#1161/#1162).
|
|
4561
|
+
base: {
|
|
4562
|
+
width: 'max-content',
|
|
4563
|
+
flexShrink: '0',
|
|
4564
|
+
flexDirection: 'row',
|
|
4565
|
+
border: '0 solid transparent',
|
|
4566
|
+
...lynxSides('border{}Width', 'var(--border)'),
|
|
4567
|
+
...lynxSides('border{}Color', 'var(--color-base-300)'),
|
|
4568
|
+
},
|
|
4569
|
+
// The frame keeps all four edges (signalxjs/lynx#1218).
|
|
4570
|
+
// It used to give up its leading edge to the first item's
|
|
4571
|
+
// seam and trust its own clip to round that item's
|
|
4572
|
+
// corners, but on iOS the frame's clip does not round the
|
|
4573
|
+
// leading corners: the first item painted square, and its
|
|
4574
|
+
// seam was lost with them. The `first`/`last` modifiers
|
|
4575
|
+
// below carry the join's ends instead.
|
|
4576
|
+
},
|
|
4577
|
+
item: {
|
|
4578
|
+
base: { flexShrink: '0', flexWrap: 'nowrap' },
|
|
4579
|
+
states: {
|
|
4580
|
+
// No hover on a touch platform: a held item takes the
|
|
4581
|
+
// wash daisy's hover gives it; an on item keeps its
|
|
4582
|
+
// fill (the selector below).
|
|
4583
|
+
pressed: { background: 'var(--color-base-300)' },
|
|
4584
|
+
// The frame clips its items, so the ring is drawn
|
|
4585
|
+
// inside the item (lynx's `outline` has no offset
|
|
4586
|
+
// and ignores the radius, lynx#1163).
|
|
4587
|
+
'focus-visible': lynxFocusRing('var(--toggle-group-accent)', { inset: true }),
|
|
4588
|
+
},
|
|
4589
|
+
selectors: {
|
|
4590
|
+
'&[data-state="on"][data-pressed]': { background: 'var(--toggle-group-accent)' },
|
|
4591
|
+
// The join seams: lynx has no sibling combinator, so
|
|
4592
|
+
// the web's `item + item` edge cannot be selected.
|
|
4593
|
+
// Every item draws its leading seam, and the `first`
|
|
4594
|
+
// modifier takes it off the item at the frame's edge.
|
|
4595
|
+
'&[data-orientation="horizontal"]': {
|
|
4596
|
+
borderLeftWidth: 'var(--border)',
|
|
4597
|
+
borderLeftStyle: 'solid',
|
|
4598
|
+
borderLeftColor: 'var(--color-base-300)',
|
|
4599
|
+
},
|
|
4600
|
+
'&[data-orientation="vertical"]': {
|
|
4601
|
+
borderTopWidth: 'var(--border)',
|
|
4602
|
+
borderTopStyle: 'solid',
|
|
4603
|
+
borderTopColor: 'var(--color-base-300)',
|
|
4604
|
+
},
|
|
4605
|
+
},
|
|
4606
|
+
},
|
|
4607
|
+
},
|
|
4608
|
+
// The ends of the join (signalxjs/lynx#1218). Lynx has no
|
|
4609
|
+
// `:first-child` or `:last-child`, so lynx-zero stamps the end
|
|
4610
|
+
// items itself, as `data-mod-first` / `data-mod-last` (the
|
|
4611
|
+
// `zx-m-first` / `zx-m-last` classes). They are a lynx-zero
|
|
4612
|
+
// rendering detail, not modifiers an author sets, so they are
|
|
4613
|
+
// not declared in the vocabulary and are styled from raw lynx
|
|
4614
|
+
// css. The end items round their own outer corners to the
|
|
4615
|
+
// frame's inner radius, so an on or held end item follows the
|
|
4616
|
+
// frame's corners without relying on its clip; `first` also
|
|
4617
|
+
// drops the leading seam, which would double the frame's edge.
|
|
4618
|
+
// That zero width is spelled through var() on purpose: a static
|
|
4619
|
+
// longhand loses to the var-bearing seam width whatever its
|
|
4620
|
+
// specificity (lynx expands var() declarations after the
|
|
4621
|
+
// cascade, signalxjs/lynx#1161).
|
|
4622
|
+
css: `
|
|
4623
|
+
.zx-toggle-group__item.zx-m-first.zx-o-horizontal {
|
|
4624
|
+
border-left-width: ${noSeam};
|
|
4625
|
+
border-top-left-radius: ${joinInnerRadius};
|
|
4626
|
+
border-bottom-left-radius: ${joinInnerRadius};
|
|
4627
|
+
}
|
|
4628
|
+
.zx-toggle-group__item.zx-m-first.zx-o-vertical {
|
|
4629
|
+
border-top-width: ${noSeam};
|
|
4630
|
+
border-top-left-radius: ${joinInnerRadius};
|
|
4631
|
+
border-top-right-radius: ${joinInnerRadius};
|
|
4632
|
+
}
|
|
4633
|
+
.zx-toggle-group__item.zx-m-last.zx-o-horizontal {
|
|
4634
|
+
border-top-right-radius: ${joinInnerRadius};
|
|
4635
|
+
border-bottom-right-radius: ${joinInnerRadius};
|
|
4636
|
+
}
|
|
4637
|
+
.zx-toggle-group__item.zx-m-last.zx-o-vertical {
|
|
4638
|
+
border-bottom-left-radius: ${joinInnerRadius};
|
|
4639
|
+
border-bottom-right-radius: ${joinInnerRadius};
|
|
4640
|
+
}
|
|
4641
|
+
`,
|
|
4642
|
+
},
|
|
4643
|
+
},
|
|
4398
4644
|
};
|
|
4399
4645
|
// daisy "join" of an input and two btns: one bordered capsule (the control),
|
|
4400
4646
|
// hairline seams on the triggers' inner edges, neutral btn fills for the steppers.
|
|
@@ -4538,14 +4784,65 @@ export const numberInput = {
|
|
|
4538
4784
|
xl: { control: { base: { height: fieldHeight('xl') } }, input: { base: { fontSize: 'var(--text-lg)', padding: 'var(--space-lg) var(--space-xl)' } } },
|
|
4539
4785
|
},
|
|
4540
4786
|
},
|
|
4541
|
-
//
|
|
4542
|
-
//
|
|
4543
|
-
//
|
|
4787
|
+
// Lynx restatements:
|
|
4788
|
+
// - the steppers' inline padding and their seams, physically: logical
|
|
4789
|
+
// spellings resolve on iOS but not on Android (measured,
|
|
4790
|
+
// signalxjs/lynx#1084);
|
|
4791
|
+
// - the steppers are views around a text glyph, with none of a
|
|
4792
|
+
// button's content centering;
|
|
4793
|
+
// - the native input takes no `inherit`: its ink is spelled out, and it
|
|
4794
|
+
// grows into any room a stretched control leaves between the steppers;
|
|
4795
|
+
// - the web root is inline-flex and hugs its content; lynx's flex column
|
|
4796
|
+
// stretches, so the children align to the start instead;
|
|
4797
|
+
// - the focus ring is `lynxFocusRing` (lynx's outline ignores the radius
|
|
4798
|
+
// and has no offset, signalxjs/lynx#1163). A shadow must not be
|
|
4799
|
+
// clipped by the box's own `overflow: hidden`, so the control stops
|
|
4800
|
+
// clipping and the steppers round their own outer corners instead.
|
|
4544
4801
|
targets: {
|
|
4545
4802
|
lynx: {
|
|
4546
4803
|
parts: {
|
|
4547
|
-
|
|
4548
|
-
|
|
4804
|
+
root: { base: { alignItems: 'flex-start' } },
|
|
4805
|
+
control: {
|
|
4806
|
+
base: { overflow: 'visible' },
|
|
4807
|
+
states: { 'focus-visible': lynxFocusRing('var(--number-input-accent)') },
|
|
4808
|
+
},
|
|
4809
|
+
// `::placeholder` does not exist on lynx, so the web's 60%
|
|
4810
|
+
// mix rides lynx's own `-x-placeholder-color` (baked per
|
|
4811
|
+
// theme) — without it the platform default reads dark on
|
|
4812
|
+
// dark (signalxjs/lynx#1222). Spelled out, not the
|
|
4813
|
+
// `textFieldPlaceholder` const: that one is declared further
|
|
4814
|
+
// down the module, after this literal is evaluated.
|
|
4815
|
+
input: {
|
|
4816
|
+
base: {
|
|
4817
|
+
color: 'var(--color-base-content)',
|
|
4818
|
+
'-x-placeholder-color': 'color-mix(in oklab, var(--color-base-content) 60%, transparent)',
|
|
4819
|
+
flexGrow: '1',
|
|
4820
|
+
},
|
|
4821
|
+
},
|
|
4822
|
+
'increment-trigger': {
|
|
4823
|
+
base: {
|
|
4824
|
+
display: 'flex',
|
|
4825
|
+
alignItems: 'center',
|
|
4826
|
+
justifyContent: 'center',
|
|
4827
|
+
paddingLeft: 'var(--space-lg)',
|
|
4828
|
+
paddingRight: 'var(--space-lg)',
|
|
4829
|
+
borderLeft: 'var(--border) solid var(--color-base-300)',
|
|
4830
|
+
borderTopRightRadius: 'var(--radius-field)',
|
|
4831
|
+
borderBottomRightRadius: 'var(--radius-field)',
|
|
4832
|
+
},
|
|
4833
|
+
},
|
|
4834
|
+
'decrement-trigger': {
|
|
4835
|
+
base: {
|
|
4836
|
+
display: 'flex',
|
|
4837
|
+
alignItems: 'center',
|
|
4838
|
+
justifyContent: 'center',
|
|
4839
|
+
paddingLeft: 'var(--space-lg)',
|
|
4840
|
+
paddingRight: 'var(--space-lg)',
|
|
4841
|
+
borderRight: 'var(--border) solid var(--color-base-300)',
|
|
4842
|
+
borderTopLeftRadius: 'var(--radius-field)',
|
|
4843
|
+
borderBottomLeftRadius: 'var(--radius-field)',
|
|
4844
|
+
},
|
|
4845
|
+
},
|
|
4549
4846
|
},
|
|
4550
4847
|
},
|
|
4551
4848
|
},
|
|
@@ -4948,6 +5245,14 @@ const affixSize = (fontSize) => ({
|
|
|
4948
5245
|
'clear-trigger': { base: { fontSize } },
|
|
4949
5246
|
'visibility-trigger': { base: { fontSize } },
|
|
4950
5247
|
});
|
|
5248
|
+
/**
|
|
5249
|
+
* A text field's placeholder ink on lynx (signalxjs/lynx#1205): the web's
|
|
5250
|
+
* `::placeholder` mix, for lynx's `-x-placeholder-color` property — the
|
|
5251
|
+
* emitter bakes the `color-mix()` to one literal per theme.
|
|
5252
|
+
*/
|
|
5253
|
+
const textFieldPlaceholder = 'color-mix(in oklab, var(--color-base-content) 60%, transparent)';
|
|
5254
|
+
/** The ghost field button's held look on lynx — the web's hover wash, on a press. */
|
|
5255
|
+
const fieldButtonHeld = { color: 'var(--color-base-content)', background: 'var(--color-base-200)' };
|
|
4951
5256
|
/**
|
|
4952
5257
|
* daisy "input" flavor: the shared field box with nothing in it but the text.
|
|
4953
5258
|
* Same `fieldControl` metrics as select's trigger, combobox's control and the
|
|
@@ -5069,7 +5374,56 @@ export const input = {
|
|
|
5069
5374
|
xl: { control: { base: { height: fieldHeight('xl') } }, input: { base: { fontSize: 'var(--text-lg)', padding: 'var(--space-lg) var(--space-xl)' } }, ...affixSize('var(--text-lg)') },
|
|
5070
5375
|
},
|
|
5071
5376
|
},
|
|
5377
|
+
// lynx (signalxjs/lynx#1205). The field is a native text widget inside
|
|
5378
|
+
// a view `control`, so what the web gets from the cascade is restated:
|
|
5379
|
+
targets: {
|
|
5380
|
+
lynx: {
|
|
5381
|
+
parts: {
|
|
5382
|
+
// The web control is an `inline-flex` row; the emitter's
|
|
5383
|
+
// `flex` rewrite keeps no direction, so the row is explicit.
|
|
5384
|
+
// No `:hover` border on a touch platform — the ring below
|
|
5385
|
+
// (box-shadow spread, signalxjs/lynx#1163) is the focus cue,
|
|
5386
|
+
// in the root's accent like the web outline.
|
|
5387
|
+
control: {
|
|
5388
|
+
base: { flexDirection: 'row' },
|
|
5389
|
+
states: { 'focus-visible': lynxFocusRing('var(--input-accent)') },
|
|
5390
|
+
},
|
|
5391
|
+
// `color: inherit` never reaches a native text field, and
|
|
5392
|
+
// `::placeholder` does not exist: the ink is explicit and the
|
|
5393
|
+
// placeholder takes lynx's own `-x-placeholder-color`, the
|
|
5394
|
+
// web's 60% mix baked per theme.
|
|
5395
|
+
input: {
|
|
5396
|
+
base: {
|
|
5397
|
+
color: 'var(--color-base-content)',
|
|
5398
|
+
'-x-placeholder-color': textFieldPlaceholder,
|
|
5399
|
+
flexGrow: '1',
|
|
5400
|
+
flexShrink: '1',
|
|
5401
|
+
},
|
|
5402
|
+
},
|
|
5403
|
+
// The adornment's edge padding, physical: Android never
|
|
5404
|
+
// resolves the logical spellings (signalxjs/lynx#1084).
|
|
5405
|
+
adornment: {
|
|
5406
|
+
selectors: {
|
|
5407
|
+
'&[data-placement="start"]': { paddingLeft: 'var(--space-md)' },
|
|
5408
|
+
'&[data-placement="end"]': { paddingRight: 'var(--space-md)' },
|
|
5409
|
+
},
|
|
5410
|
+
},
|
|
5411
|
+
// Same for the ghost buttons' end margin; the web's `:hover`
|
|
5412
|
+
// wash answers a press instead.
|
|
5413
|
+
'clear-trigger': {
|
|
5414
|
+
base: { marginRight: 'var(--space-xs)' },
|
|
5415
|
+
states: { pressed: fieldButtonHeld },
|
|
5416
|
+
},
|
|
5417
|
+
'visibility-trigger': {
|
|
5418
|
+
base: { marginRight: 'var(--space-xs)' },
|
|
5419
|
+
states: { pressed: fieldButtonHeld },
|
|
5420
|
+
},
|
|
5421
|
+
},
|
|
5422
|
+
},
|
|
5423
|
+
},
|
|
5072
5424
|
};
|
|
5425
|
+
/** The lynx textarea floor: two field heights, as ONE calc() (signalxjs/lynx#1219). */
|
|
5426
|
+
const textareaFloor = (step) => `calc(var(--size-field) * ${FIELD_STEPS[step] * 2})`;
|
|
5073
5427
|
/**
|
|
5074
5428
|
* daisy "textarea" flavor. The `fieldControl` box minus its `height`: the
|
|
5075
5429
|
* whole point of a textarea is that its height is the content's (and the
|
|
@@ -5136,6 +5490,64 @@ export const textarea = {
|
|
|
5136
5490
|
xl: { textarea: { base: { fontSize: 'var(--text-lg)', minHeight: `calc(${fieldHeight('xl')} * 2)`, padding: 'var(--space-lg) var(--space-xl)' } } },
|
|
5137
5491
|
},
|
|
5138
5492
|
},
|
|
5493
|
+
// lynx (signalxjs/lynx#1205): lynx-zero renders the part as a view (the
|
|
5494
|
+
// box, whose state classes repaint) around the native field, which wears
|
|
5495
|
+
// the part's base class as its text face. So the ink and the placeholder
|
|
5496
|
+
// are explicit here — `color: inherit` and `::placeholder` never reach a
|
|
5497
|
+
// native widget — and the web's `:hover` border and outline ring become
|
|
5498
|
+
// the lynx focus ring in the root's accent (signalxjs/lynx#1163).
|
|
5499
|
+
//
|
|
5500
|
+
// The floor is one flat `calc(var(--size-field) * n)` per size
|
|
5501
|
+
// (signalxjs/lynx#1219): the shared `calc(fieldHeight * 2)` nests a
|
|
5502
|
+
// calc() in a calc(), and on device the box never took it — an empty
|
|
5503
|
+
// textarea sat one line tall.
|
|
5504
|
+
//
|
|
5505
|
+
// The focus ring is NOT `lynxFocusRing`'s two stacked outset shadows
|
|
5506
|
+
// (signalxjs/lynx#1220). Lynx iOS re-inserts a view's outset shadow
|
|
5507
|
+
// layers at a stale index whenever it re-lays the view out
|
|
5508
|
+
// (`LynxBackgroundManager.updateShadow` reads the sublayer count before
|
|
5509
|
+
// removing the old layers), which reverses their stacking: the 4px ring
|
|
5510
|
+
// lands on top of the 2px gap and paints one solid band. A fixed-height
|
|
5511
|
+
// box never re-lays out; this auto-height one does, as its native field
|
|
5512
|
+
// measures and grows. So the ring is spelled with one outset shadow and
|
|
5513
|
+
// one inset shadow, which paint disjoint areas and cannot swap: the ring
|
|
5514
|
+
// just outside the box, the box's own border repainted as the base-100
|
|
5515
|
+
// gap, and the hairline redrawn inside it by the inset spread, in the
|
|
5516
|
+
// edge colour (`--textarea-edge`, the error colour while invalid). The
|
|
5517
|
+
// gap is the border's width instead of the web's 2px.
|
|
5518
|
+
targets: {
|
|
5519
|
+
lynx: {
|
|
5520
|
+
parts: {
|
|
5521
|
+
textarea: {
|
|
5522
|
+
base: {
|
|
5523
|
+
color: 'var(--color-base-content)',
|
|
5524
|
+
'-x-placeholder-color': textFieldPlaceholder,
|
|
5525
|
+
'--textarea-edge': 'var(--color-base-300)',
|
|
5526
|
+
minHeight: textareaFloor('md'),
|
|
5527
|
+
},
|
|
5528
|
+
states: {
|
|
5529
|
+
invalid: { '--textarea-edge': 'var(--color-error)' },
|
|
5530
|
+
'focus-visible': {
|
|
5531
|
+
outline: 'none',
|
|
5532
|
+
borderColor: 'var(--color-base-100)',
|
|
5533
|
+
boxShadow: '0 0 0 2px var(--textarea-accent), '
|
|
5534
|
+
// Twice the border (1px in every shipped
|
|
5535
|
+
// theme): the inner half shows as the hairline.
|
|
5536
|
+
+ 'inset 0 0 0 2px var(--textarea-edge)',
|
|
5537
|
+
},
|
|
5538
|
+
},
|
|
5539
|
+
},
|
|
5540
|
+
},
|
|
5541
|
+
variants: {
|
|
5542
|
+
size: {
|
|
5543
|
+
xs: { textarea: { base: { minHeight: textareaFloor('xs') } } },
|
|
5544
|
+
sm: { textarea: { base: { minHeight: textareaFloor('sm') } } },
|
|
5545
|
+
lg: { textarea: { base: { minHeight: textareaFloor('lg') } } },
|
|
5546
|
+
xl: { textarea: { base: { minHeight: textareaFloor('xl') } } },
|
|
5547
|
+
},
|
|
5548
|
+
},
|
|
5549
|
+
},
|
|
5550
|
+
},
|
|
5139
5551
|
};
|
|
5140
5552
|
// ── Content tier (#311) ───────────────────────────────────────────────────
|
|
5141
5553
|
/**
|