@sigx/zero-daisyui 0.2.0-beta.4 → 0.2.0-beta.6

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.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://signalxjs.github.io/zero/schemas/lynx-manifest.schema.json",
3
3
  "manifestVersion": 1,
4
- "zeroVersion": "0.2.0-beta.4",
4
+ "zeroVersion": "0.2.0-beta.6",
5
5
  "name": "daisyui",
6
6
  "themes": [
7
7
  {
@@ -1803,6 +1803,6 @@
1803
1803
  "classGrammarVersion": 1,
1804
1804
  "capabilities": {
1805
1805
  "translated": 60,
1806
- "dropped": 227
1806
+ "dropped": 324
1807
1807
  }
1808
1808
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://signalxjs.github.io/zero/schemas/ds-manifest.schema.json",
3
3
  "manifestVersion": 1,
4
- "zeroVersion": "0.2.0-beta.4",
4
+ "zeroVersion": "0.2.0-beta.6",
5
5
  "name": "daisyui",
6
6
  "themes": [
7
7
  {
@@ -1 +1 @@
1
- {"version":3,"file":"recipes.d.ts","sourceRoot":"","sources":["../src/recipes.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"recipes.d.ts","sourceRoot":"","sources":["../src/recipes.ts"],"names":[],"mappings":"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"}
package/dist/recipes.js CHANGED
@@ -436,18 +436,33 @@ export const tabs = {
436
436
  defaultVariants: { size: 'md', variant: 'border' },
437
437
  targets: {
438
438
  lynx: {
439
+ parts: {
440
+ // The default active ink — base-content, exactly what the
441
+ // shared `states.active.color` paints. One class, so any
442
+ // color-axis definition below (host + two classes, baked per
443
+ // theme) wins on specificity.
444
+ tab: { base: { '--tab-active-ink': 'var(--color-base-content)' } },
445
+ },
439
446
  variants: {
447
+ // `currentColor` never resolves on lynx (measured on device
448
+ // on both platforms, signalxjs/lynx#1079 — the underline was
449
+ // transparent everywhere), so the color axis restates its
450
+ // active ink as a plain custom property. `roleInk` reads
451
+ // theme colors through color-mix(), which the emitter bakes
452
+ // once per theme — the same per-color/per-theme literal the
453
+ // active `color:` rules already land as.
454
+ color: Object.fromEntries(ROLES.map((c) => [c, { tab: { base: { '--tab-active-ink': roleInk(c) } } }])),
440
455
  variant: {
441
456
  // The underline is a ::before on the web, which lynx
442
457
  // drops — redrawn as a real bottom border on the tab
443
458
  // itself (transparent at rest so activation never moves
444
- // the row). `currentColor` keeps it following the color
445
- // axis ink, the same mechanism switch's shared border
446
- // already relies on for lynx.
459
+ // the row). The active ink rides `--tab-active-ink`
460
+ // above — a plain var() chain, device-proven — instead
461
+ // of `currentColor`, which lynx never resolves.
447
462
  border: {
448
463
  tab: {
449
464
  base: { borderBottom: '3px solid transparent' },
450
- states: { active: { borderBottomColor: 'currentColor' } },
465
+ states: { active: { borderBottomColor: 'var(--tab-active-ink)' } },
451
466
  },
452
467
  },
453
468
  // `min()` does not exist on lynx (signalxjs/lynx#1066) and
@@ -862,6 +877,24 @@ const btnSizes = {
862
877
  lg: { trigger: { base: { height: fieldHeight('lg'), paddingInline: 'calc(var(--size-field) * 5)', fontSize: 'var(--text-md)' } } },
863
878
  xl: { trigger: { base: { height: fieldHeight('xl'), paddingInline: 'calc(var(--size-field) * 6)', fontSize: 'var(--text-lg)' } } },
864
879
  };
880
+ /**
881
+ * `btn`'s inline padding restated physically, for the `targets.lynx`
882
+ * sections of every btn-wearing recipe: logical spellings resolve on iOS but
883
+ * not on Android (measured, signalxjs/lynx#1084), so the lynx emitter
884
+ * refuses `padding-inline`. Physical is that target's norm — lynx has no
885
+ * RTL flow for the logical spelling to flip with.
886
+ */
887
+ const lynxBtnPad = (mult) => ({
888
+ paddingLeft: `calc(var(--size-field) * ${mult})`,
889
+ paddingRight: `calc(var(--size-field) * ${mult})`,
890
+ });
891
+ /** The btn size ramp's physical inline padding, for `targets.lynx.variants`. */
892
+ const lynxBtnSizes = (part) => ({
893
+ xs: { [part]: { base: lynxBtnPad(2) } },
894
+ sm: { [part]: { base: lynxBtnPad(3) } },
895
+ lg: { [part]: { base: lynxBtnPad(5) } },
896
+ xl: { [part]: { base: lynxBtnPad(6) } },
897
+ });
865
898
  export const dialog = {
866
899
  component: 'dialog',
867
900
  keyframes: {
@@ -942,6 +975,19 @@ export const dialog = {
942
975
  // Trigger-carried axes — see `btnColors` for why the popup is out of
943
976
  // reach and the trigger is the whole story here.
944
977
  variants: { color: btnColors(), size: btnSizes },
978
+ // The btn paddings and the footer's push-down, restated physically —
979
+ // see `lynxBtnPad` for the #1084 verdict this answers.
980
+ targets: {
981
+ lynx: {
982
+ parts: {
983
+ trigger: { base: lynxBtnPad(4) },
984
+ close: { base: lynxBtnPad(4) },
985
+ cancel: { base: lynxBtnPad(4) },
986
+ footer: { base: { marginTop: '1.5rem' } },
987
+ },
988
+ variants: { size: lynxBtnSizes('trigger') },
989
+ },
990
+ },
945
991
  };
946
992
  // daisy "dropdown-content"/card look for floating panels.
947
993
  const floatingPanel = {
@@ -982,6 +1028,16 @@ export const popover = {
982
1028
  },
983
1029
  // Trigger-carried axes — same wiring as dialog, same reason.
984
1030
  variants: { color: btnColors(), size: btnSizes },
1031
+ // The btn paddings, restated physically — see `lynxBtnPad` (#1084).
1032
+ targets: {
1033
+ lynx: {
1034
+ parts: {
1035
+ trigger: { base: lynxBtnPad(4) },
1036
+ close: { base: lynxBtnPad(3) },
1037
+ },
1038
+ variants: { size: lynxBtnSizes('trigger') },
1039
+ },
1040
+ },
985
1041
  };
986
1042
  export const tooltip = {
987
1043
  component: 'tooltip',
@@ -1017,6 +1073,13 @@ export const tooltip = {
1017
1073
  // Trigger-carried axes — same wiring as dialog, same reason. The bubble
1018
1074
  // stays daisy's neutral tooltip whatever the trigger's colour.
1019
1075
  variants: { color: btnColors(), size: btnSizes },
1076
+ // The btn paddings, restated physically — see `lynxBtnPad` (#1084).
1077
+ targets: {
1078
+ lynx: {
1079
+ parts: { trigger: { base: lynxBtnPad(4) } },
1080
+ variants: { size: lynxBtnSizes('trigger') },
1081
+ },
1082
+ },
1020
1083
  };
1021
1084
  // daisy "menu in a dropdown" look.
1022
1085
  export const menu = {
@@ -1162,6 +1225,13 @@ export const menu = {
1162
1225
  // Trigger-carried axes — same wiring as dialog, same reason. The dropdown
1163
1226
  // and its items are top-layer siblings the donut cannot reach.
1164
1227
  variants: { color: btnColors(), size: btnSizes },
1228
+ // The btn paddings, restated physically — see `lynxBtnPad` (#1084).
1229
+ targets: {
1230
+ lynx: {
1231
+ parts: { trigger: { base: lynxBtnPad(4) } },
1232
+ variants: { size: lynxBtnSizes('trigger') },
1233
+ },
1234
+ },
1165
1235
  };
1166
1236
  export const field = {
1167
1237
  component: 'field',
@@ -1427,6 +1497,45 @@ export const checkbox = {
1427
1497
  // control and its text. Declared rather than left implicit so the
1428
1498
  // delegation reads as a decision.
1429
1499
  skipStates: { root: ['focus-visible'] },
1500
+ // `currentColor` never resolves on lynx (measured on device on both
1501
+ // platforms, signalxjs/lynx#1079), so the tick shipped invisible and the
1502
+ // ring's color-mix-over-currentColor fallback dropped the whole border.
1503
+ // Both restated with the named accents the web spellings resolve to —
1504
+ // plain var() chains, the switch's device-proven #380 mechanism.
1505
+ targets: {
1506
+ lynx: {
1507
+ parts: {
1508
+ control: {
1509
+ // The web fallback (`color-mix(in oklab, … currentColor …)`)
1510
+ // exists for consumers that unset the accent; this package
1511
+ // always defines it, so the plain accent IS the ring.
1512
+ base: { border: 'var(--border) solid var(--checkbox-accent)' },
1513
+ },
1514
+ indicator: {
1515
+ // The tick's fill: the control's `color:` names
1516
+ // `--checkbox-on-accent`, and `currentColor` was that
1517
+ // ink by inheritance — spend it directly.
1518
+ //
1519
+ // The tick's motion, restated as `transform`: the
1520
+ // standalone `rotate`/`translate` properties resolve on
1521
+ // iOS but not on Android (measured, signalxjs/lynx#1084),
1522
+ // so the emitter refuses them. `transform` functions are
1523
+ // proven on both platforms — and the transition follows
1524
+ // the property that now moves.
1525
+ base: {
1526
+ backgroundColor: 'var(--checkbox-on-accent)',
1527
+ transform: 'rotate(45deg)',
1528
+ transition: 'clip-path var(--duration-slow) var(--ease-standard) var(--duration-instant), '
1529
+ + 'opacity var(--duration-instant) var(--ease-standard) var(--duration-instant), '
1530
+ + 'transform var(--duration-slow) var(--ease-standard) var(--duration-instant)',
1531
+ },
1532
+ // The order matches the standalone properties' fixed
1533
+ // apply order (translate, then rotate).
1534
+ states: { indeterminate: { transform: 'translateY(-35%) rotate(0deg)' } },
1535
+ },
1536
+ },
1537
+ },
1538
+ },
1430
1539
  };
1431
1540
  // --------------------------------------------------------------------------
1432
1541
  // 3. radioGroup — replace the whole export
@@ -1542,6 +1651,25 @@ export const radioGroup = {
1542
1651
  // wraps it. Declared rather than left implicit so the delegation reads
1543
1652
  // as a decision.
1544
1653
  skipStates: { item: ['focus-visible'] },
1654
+ // `currentColor` never resolves on lynx (measured on device on both
1655
+ // platforms, signalxjs/lynx#1079), so the checked ring and dot shipped
1656
+ // invisible, and the unchecked ring's color-mix-over-currentColor
1657
+ // fallback dropped the whole border. All three restated with the accent
1658
+ // the control's own `color:` names — plain var() chains, the switch's
1659
+ // device-proven #380 mechanism.
1660
+ targets: {
1661
+ lynx: {
1662
+ parts: {
1663
+ 'item-control': {
1664
+ base: { border: 'var(--border) solid var(--radio-accent)' },
1665
+ states: { checked: { borderColor: 'var(--radio-accent)' } },
1666
+ },
1667
+ 'item-indicator': {
1668
+ states: { checked: { backgroundColor: 'var(--radio-accent)' } },
1669
+ },
1670
+ },
1671
+ },
1672
+ },
1545
1673
  };
1546
1674
  // --------------------------------------------------------------------------
1547
1675
  // 4. progress — replace the whole export (only the two radius lines move)
@@ -1649,6 +1777,18 @@ export const progress = {
1649
1777
  // other way.
1650
1778
  'zero-daisy-indeterminate': 'from { margin-inline-start: -40%; } to { margin-inline-start: 100%; }',
1651
1779
  },
1780
+ // The same sweep with a physical margin: logical spellings resolve on
1781
+ // iOS but not on Android (measured, signalxjs/lynx#1084), so the emitter
1782
+ // refuses the shared keyframes. Physical is the lynx target's norm — no
1783
+ // RTL flow there for the sweep to mirror with. Keyframes merge per name,
1784
+ // so this REPLACES the shared animation on lynx.
1785
+ targets: {
1786
+ lynx: {
1787
+ keyframes: {
1788
+ 'zero-daisy-indeterminate': 'from { margin-left: -40%; } to { margin-left: 100%; }',
1789
+ },
1790
+ },
1791
+ },
1652
1792
  };
1653
1793
  export const slider = {
1654
1794
  component: 'slider',
@@ -1773,6 +1913,22 @@ export const slider = {
1773
1913
  targets: {
1774
1914
  lynx: {
1775
1915
  parts: {
1916
+ track: {
1917
+ // The web track's `margin-block` breathing room,
1918
+ // restated physically: logical spellings resolve on iOS
1919
+ // but not on Android (measured, signalxjs/lynx#1084), so
1920
+ // the emitter refuses them. Physical is the lynx
1921
+ // target's norm — no RTL flow there.
1922
+ base: {
1923
+ marginTop: 'calc(var(--size-selector) * 1.5)',
1924
+ marginBottom: 'calc(var(--size-selector) * 1.5)',
1925
+ },
1926
+ },
1927
+ mark: {
1928
+ // Same #1084 verdict: the tick labels hang below the
1929
+ // track off a physical padding.
1930
+ base: { paddingTop: 'calc(var(--size-selector) * 2 + var(--space-2xs))' },
1931
+ },
1776
1932
  range: {
1777
1933
  // The web fill deepens the accent 90/10 toward
1778
1934
  // base-content (`progressFill`'s recipe); the plain
@@ -1796,9 +1952,20 @@ export const slider = {
1796
1952
  // thumb — a native-input trick with no lynx equivalent;
1797
1953
  // the composed `.zx-slider__range` box above IS that
1798
1954
  // fill here, so the knob only needs its own two paints.
1955
+ //
1956
+ // The centering geometry is restated physically beside
1957
+ // the paint: `inset-block-start`/`translate`/
1958
+ // `margin-inline-start` resolve on iOS but not on
1959
+ // Android (measured, signalxjs/lynx#1084 — the knob sat
1960
+ // off-center there), so the emitter refuses them.
1961
+ // `top` + `transform: translateY()` + `margin-left` are
1962
+ // proven on both platforms.
1799
1963
  base: {
1800
1964
  background: 'var(--color-base-100)',
1801
1965
  border: '0.25rem solid var(--slider-accent)',
1966
+ top: '50%',
1967
+ transform: 'translateY(-50%)',
1968
+ marginLeft: 'calc(var(--size-selector) * -2.5)',
1802
1969
  },
1803
1970
  },
1804
1971
  },
@@ -2016,6 +2183,17 @@ export const select = {
2016
2183
  // Base equals the default (`tokens:` accent, `fieldControl`'s md height),
2017
2184
  // so the twins restate it; declared for the manifest (signalxjs/lynx#1070).
2018
2185
  defaultVariants: { color: 'primary', size: 'md' },
2186
+ // The btn paddings, restated physically — see `lynxBtnPad` (#1084).
2187
+ // The trigger ramp restates `md` too (unlike `btnSizes`), so its lynx
2188
+ // counterpart does as well.
2189
+ targets: {
2190
+ lynx: {
2191
+ parts: { trigger: { base: lynxBtnPad(4) } },
2192
+ variants: {
2193
+ size: { ...lynxBtnSizes('trigger'), md: { trigger: { base: lynxBtnPad(4) } } },
2194
+ },
2195
+ },
2196
+ },
2019
2197
  };
2020
2198
  /**
2021
2199
  * daisy's BUTTON ramp — `.btn`'s fixed height per size step, in `--size-field`
@@ -2239,6 +2417,17 @@ export const button = {
2239
2417
  },
2240
2418
  defaultVariants: { color: 'primary', variant: 'solid', size: 'md' },
2241
2419
  keyframes: { 'zero-daisyui-btn-spin': 'to { transform: rotate(360deg) }' },
2420
+ // The icon chips' zeroed inline padding, restated physically: logical
2421
+ // spellings resolve on iOS but not on Android (measured,
2422
+ // signalxjs/lynx#1084), so the emitter refuses them.
2423
+ targets: {
2424
+ lynx: {
2425
+ modifiers: {
2426
+ square: { root: { base: { paddingLeft: '0', paddingRight: '0' } } },
2427
+ circle: { root: { base: { paddingLeft: '0', paddingRight: '0' } } },
2428
+ },
2429
+ },
2430
+ },
2242
2431
  };
2243
2432
  export const avatar = {
2244
2433
  component: 'avatar',
@@ -2464,6 +2653,24 @@ export const toast = {
2464
2653
  // signalxjs/lynx#1070. No `color` default: the un-attributed toast is a
2465
2654
  // neutral base-200 surface, outside the color vocabulary.
2466
2655
  defaultVariants: { size: 'md' },
2656
+ // The corner placements' physical anchors: logical inset spellings
2657
+ // resolve on iOS but not on Android (measured, signalxjs/lynx#1084), so
2658
+ // the emitter refuses them. Physical is the lynx target's norm — no RTL
2659
+ // flow there, so `start` IS left and `end` IS right.
2660
+ targets: {
2661
+ lynx: {
2662
+ parts: {
2663
+ viewport: {
2664
+ selectors: {
2665
+ '&[data-placement="top-start"]': { left: '0' },
2666
+ '&[data-placement="top-end"]': { right: '0' },
2667
+ '&[data-placement="bottom-start"]': { left: '0' },
2668
+ '&[data-placement="bottom-end"]': { right: '0' },
2669
+ },
2670
+ },
2671
+ },
2672
+ },
2673
+ },
2467
2674
  };
2468
2675
  export const combobox = {
2469
2676
  component: 'combobox',
@@ -2938,6 +3145,17 @@ export const numberInput = {
2938
3145
  xl: { control: { base: { height: fieldHeight('xl') } }, input: { base: { fontSize: 'var(--text-lg)', padding: 'var(--space-lg) var(--space-xl)' } } },
2939
3146
  },
2940
3147
  },
3148
+ // The steppers' inline padding, restated physically: logical spellings
3149
+ // resolve on iOS but not on Android (measured, signalxjs/lynx#1084), so
3150
+ // the emitter refuses them.
3151
+ targets: {
3152
+ lynx: {
3153
+ parts: {
3154
+ 'increment-trigger': { base: { paddingLeft: 'var(--space-lg)', paddingRight: 'var(--space-lg)' } },
3155
+ 'decrement-trigger': { base: { paddingLeft: 'var(--space-lg)', paddingRight: 'var(--space-lg)' } },
3156
+ },
3157
+ },
3158
+ },
2941
3159
  };
2942
3160
  /**
2943
3161
  * daisy "rating" flavor: a row of orange filled symbols. The default content
@@ -3227,6 +3445,16 @@ export const treeView = {
3227
3445
  xl: { root: { base: { '--tree-text': 'var(--text-lg)' } } },
3228
3446
  },
3229
3447
  },
3448
+ // The indent, restated physically: logical spellings resolve on iOS but
3449
+ // not on Android (measured, signalxjs/lynx#1084), so the emitter refuses
3450
+ // them. Physical is the lynx target's norm — no RTL flow there.
3451
+ targets: {
3452
+ lynx: {
3453
+ parts: {
3454
+ 'branch-content': { base: { paddingLeft: 'var(--space-lg)' } },
3455
+ },
3456
+ },
3457
+ },
3230
3458
  };
3231
3459
  /**
3232
3460
  * daisy "input" flavor: the shared field box with nothing in it but the text.
@@ -3446,6 +3674,26 @@ export const nativeSelect = {
3446
3674
  xl: { control: { base: { height: fieldHeight('xl'), fontSize: 'var(--text-lg)', padding: 'var(--space-lg) var(--space-xl)', paddingInlineEnd: 'calc(var(--space-xl) + 1.25em)' } } },
3447
3675
  },
3448
3676
  },
3677
+ // The chevron gutter and the indicator anchor, restated physically:
3678
+ // logical spellings resolve on iOS but not on Android (measured,
3679
+ // signalxjs/lynx#1084), so the emitter refuses them. Physical is the
3680
+ // lynx target's norm — no RTL flow there, so `end` IS right.
3681
+ targets: {
3682
+ lynx: {
3683
+ parts: {
3684
+ control: { base: { paddingRight: 'calc(var(--space-md) + 1.25em)' } },
3685
+ indicator: { base: { right: 'var(--space-md)' } },
3686
+ },
3687
+ variants: {
3688
+ size: {
3689
+ xs: { control: { base: { paddingRight: 'calc(var(--space-xs) + 1.25em)' } } },
3690
+ sm: { control: { base: { paddingRight: 'calc(var(--space-sm) + 1.25em)' } } },
3691
+ lg: { control: { base: { paddingRight: 'calc(var(--space-lg) + 1.25em)' } } },
3692
+ xl: { control: { base: { paddingRight: 'calc(var(--space-xl) + 1.25em)' } } },
3693
+ },
3694
+ },
3695
+ },
3696
+ },
3449
3697
  };
3450
3698
  // ── Content tier (#311) ───────────────────────────────────────────────────
3451
3699
  /**
@@ -3910,6 +4158,30 @@ export const indicator = {
3910
4158
  xl: { item: { base: { fontSize: 'var(--text-lg)' } } },
3911
4159
  },
3912
4160
  },
4161
+ // The corner slots, restated physically: logical inset spellings and the
4162
+ // standalone `translate` property resolve on iOS but not on Android
4163
+ // (measured, signalxjs/lynx#1084), so the emitter refuses them. Physical
4164
+ // anchors plus `transform: translate()` are proven on both platforms,
4165
+ // and physical is the lynx target's norm — no RTL flow there, so the
4166
+ // hand-flipped RTL rules above have nothing to engage with either.
4167
+ targets: {
4168
+ lynx: {
4169
+ parts: {
4170
+ item: {
4171
+ selectors: {
4172
+ '&[data-placement="top-start"]': { top: '0', left: '0', transform: 'translate(-50%, -50%)' },
4173
+ '&[data-placement="top"]': { top: '0', left: '50%', transform: 'translate(-50%, -50%)' },
4174
+ '&[data-placement="top-end"]': { top: '0', right: '0', transform: 'translate(50%, -50%)' },
4175
+ '&[data-placement="start"]': { top: '50%', left: '0', transform: 'translate(-50%, -50%)' },
4176
+ '&[data-placement="end"]': { top: '50%', right: '0', transform: 'translate(50%, -50%)' },
4177
+ '&[data-placement="bottom-start"]': { bottom: '0', left: '0', transform: 'translate(-50%, 50%)' },
4178
+ '&[data-placement="bottom"]': { bottom: '0', left: '50%', transform: 'translate(-50%, 50%)' },
4179
+ '&[data-placement="bottom-end"]': { bottom: '0', right: '0', transform: 'translate(50%, 50%)' },
4180
+ },
4181
+ },
4182
+ },
4183
+ },
4184
+ },
3913
4185
  };
3914
4186
  /** daisy stats: the rounded base-100 panel with rule-thin item joins. */
3915
4187
  export const stats = {
@@ -4227,6 +4499,16 @@ export const chat = {
4227
4499
  xl: { bubble: { base: { fontSize: 'var(--text-lg)', padding: 'var(--space-md) var(--space-xl)' } } },
4228
4500
  },
4229
4501
  },
4502
+ // The row's vertical padding, restated physically: logical spellings
4503
+ // resolve on iOS but not on Android (measured, signalxjs/lynx#1084), so
4504
+ // the emitter refuses them.
4505
+ targets: {
4506
+ lynx: {
4507
+ parts: {
4508
+ root: { base: { paddingTop: 'var(--space-2xs)', paddingBottom: 'var(--space-2xs)' } },
4509
+ },
4510
+ },
4511
+ },
4230
4512
  };
4231
4513
  /** daisy radial-progress: --value became --progress-percent; same ring. */
4232
4514
  export const radialProgress = {
@@ -4678,6 +4960,16 @@ export const pagination = {
4678
4960
  xl: { root: { base: { '--pg-size': 'calc(var(--size-field) * 14)', '--pg-font': 'var(--text-lg)' } } },
4679
4961
  },
4680
4962
  },
4963
+ // The cell's inline padding, restated physically: logical spellings
4964
+ // resolve on iOS but not on Android (measured, signalxjs/lynx#1084), so
4965
+ // the emitter refuses them.
4966
+ targets: {
4967
+ lynx: {
4968
+ parts: {
4969
+ item: { base: { paddingLeft: 'var(--space-2xs)', paddingRight: 'var(--space-2xs)' } },
4970
+ },
4971
+ },
4972
+ },
4681
4973
  };
4682
4974
  /**
4683
4975
  * Steps — daisy's steps translated to the richer rail: bold numbered discs
@@ -4824,6 +5116,34 @@ export const steps = {
4824
5116
  xl: { root: { base: { '--steps-ind': 'calc(var(--size-selector) * 9)', '--steps-font': 'var(--text-md)' } } },
4825
5117
  },
4826
5118
  },
5119
+ // The bridge's anchors and the vertical item's tail padding, restated
5120
+ // physically: logical spellings resolve on iOS but not on Android
5121
+ // (measured, signalxjs/lynx#1084), so the emitter refuses them. Physical
5122
+ // is the lynx target's norm — no RTL flow there to mirror with.
5123
+ targets: {
5124
+ lynx: {
5125
+ parts: {
5126
+ item: {
5127
+ selectors: {
5128
+ '&[data-orientation="vertical"]': { paddingBottom: 'var(--space-lg)' },
5129
+ },
5130
+ },
5131
+ separator: {
5132
+ selectors: {
5133
+ '&[data-orientation="horizontal"]': {
5134
+ top: 'calc(var(--space-xs) + var(--steps-ind) / 2)',
5135
+ left: '50%',
5136
+ },
5137
+ '&[data-orientation="vertical"]': {
5138
+ left: 'calc(var(--space-xs) + (var(--steps-ind) - var(--border)) / 2)',
5139
+ top: 'calc(var(--space-xs) + var(--steps-ind))',
5140
+ bottom: 'calc(var(--space-xs) * -1)',
5141
+ },
5142
+ },
5143
+ },
5144
+ },
5145
+ },
5146
+ },
4827
5147
  };
4828
5148
  /**
4829
5149
  * Drawer — daisy's drawer-side as a native <dialog> edge sheet: base-100
@@ -4896,6 +5216,16 @@ export const drawer = {
4896
5216
  // Trigger-carried axes — see `btnColors` for why the panel is out of
4897
5217
  // reach and the trigger is the whole story here.
4898
5218
  variants: { color: btnColors(), size: btnSizes },
5219
+ // The btn paddings, restated physically — see `lynxBtnPad` (#1084).
5220
+ targets: {
5221
+ lynx: {
5222
+ parts: {
5223
+ trigger: { base: lynxBtnPad(4) },
5224
+ close: { base: lynxBtnPad(4) },
5225
+ },
5226
+ variants: { size: lynxBtnSizes('trigger') },
5227
+ },
5228
+ },
4899
5229
  };
4900
5230
  /**
4901
5231
  * Table — daisy's `table`: quiet base-200 row rules in a rounded box,
@@ -5283,6 +5613,22 @@ export const carousel = {
5283
5613
  xl: { root: { base: { '--carousel-dot': '0.875rem', '--carousel-nav': '3rem' } } },
5284
5614
  },
5285
5615
  },
5616
+ // The nav buttons' anchors, restated physically: logical inset
5617
+ // spellings resolve on iOS but not on Android (measured,
5618
+ // signalxjs/lynx#1084), so the emitter refuses them. Physical is the
5619
+ // lynx target's norm — no RTL flow there, so `start` IS left.
5620
+ targets: {
5621
+ lynx: {
5622
+ parts: {
5623
+ 'prev-trigger': {
5624
+ base: { top: 'calc(50% - var(--carousel-nav) / 2)', left: 'var(--space-sm)' },
5625
+ },
5626
+ 'next-trigger': {
5627
+ base: { top: 'calc(50% - var(--carousel-nav) / 2)', right: 'var(--space-sm)' },
5628
+ },
5629
+ },
5630
+ },
5631
+ },
5286
5632
  };
5287
5633
  /**
5288
5634
  * Swap — daisy's signature swap-rotate as the ONE look: the leaving face
@@ -5524,6 +5870,21 @@ export const diff = {
5524
5870
  },
5525
5871
  },
5526
5872
  },
5873
+ // The reveal pane's pin and the handle's centering margin, restated
5874
+ // physically: logical spellings resolve on iOS but not on Android
5875
+ // (measured, signalxjs/lynx#1084), so the emitter refuses them.
5876
+ // Physical is the lynx target's norm — no RTL flow there to mirror
5877
+ // with.
5878
+ lynx: {
5879
+ parts: {
5880
+ after: {
5881
+ base: { top: '0', bottom: '0', left: '0' },
5882
+ },
5883
+ handle: {
5884
+ base: { top: '0', bottom: '0', marginLeft: 'calc(var(--diff-hit) / -2)' },
5885
+ },
5886
+ },
5887
+ },
5527
5888
  },
5528
5889
  };
5529
5890
  export const recipes = [