@sigx/zero-daisyui 0.15.0 → 0.16.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.
@@ -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.15.0",
4
+ "zeroVersion": "0.16.0",
5
5
  "name": "daisyui",
6
6
  "themes": [
7
7
  {
@@ -2289,7 +2289,7 @@
2289
2289
  "target": "lynx",
2290
2290
  "classGrammarVersion": 2,
2291
2291
  "capabilities": {
2292
- "translated": 176,
2293
- "dropped": 471
2292
+ "translated": 177,
2293
+ "dropped": 467
2294
2294
  }
2295
2295
  }
@@ -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.15.0",
4
+ "zeroVersion": "0.16.0",
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
@@ -1348,7 +1348,17 @@ export const tooltip = {
1348
1348
  targets: {
1349
1349
  web: floatingArrow('tooltip', { background: 'var(--color-neutral)' }, '0.5rem'),
1350
1350
  lynx: {
1351
- parts: { trigger: { base: lynxBtnPad(4) } },
1351
+ parts: {
1352
+ // Content-sized like daisy's btn, never broken mid-word
1353
+ // (signalxjs/lynx#1165). No pressed rule: the anatomy
1354
+ // declares none — the long press paints the `open` state.
1355
+ trigger: { base: { ...lynxBtnPad(4), ...lynxBtnFit } },
1356
+ // The arrow's paint: the bubble's neutral, continued. The
1357
+ // web's `floatingArrow` geometry rides runtime custom
1358
+ // properties lynx does not write, so lynx-zero places the
1359
+ // 8px square and turns it itself (signalxjs/lynx#1277).
1360
+ arrow: { base: { background: 'var(--color-neutral)' } },
1361
+ },
1352
1362
  variants: { size: lynxBtnSizes('trigger') },
1353
1363
  },
1354
1364
  },
@@ -4527,6 +4537,70 @@ export const combobox = {
4527
4537
  },
4528
4538
  targets: {
4529
4539
  web: { parts: { popup: { base: anchoredListbox } } },
4540
+ // lynx-zero's combobox (signalxjs/lynx#1278): a native text field in
4541
+ // a painted `control` view, the list in the overlay outlet.
4542
+ lynx: {
4543
+ parts: {
4544
+ // select's bounds (signalxjs/lynx#1146): 20rem, never wider
4545
+ // than the container. The web's 13rem control floor
4546
+ // overflowed any cell narrower than 208px on a phone; the
4547
+ // control fills the root instead.
4548
+ root: { base: { width: '20rem', maxWidth: '100%', minWidth: '3rem' } },
4549
+ // The web `:hover` border is dropped on a touch platform. The
4550
+ // ring is the box-shadow spelling (signalxjs/lynx#1163): lynx
4551
+ // has no `outline-offset`, and its outline ignores the radius.
4552
+ control: {
4553
+ base: { minWidth: '3rem', width: '100%' },
4554
+ states: lynxFocus(),
4555
+ },
4556
+ // `color: inherit` never reaches a native text field, and
4557
+ // `::placeholder` does not exist: the ink is explicit, and the
4558
+ // placeholder takes lynx's `-x-placeholder-color` — the web's
4559
+ // 60% mix, baked per theme (input's spelling; its constant is
4560
+ // declared below this recipe, so the value is restated).
4561
+ input: {
4562
+ base: {
4563
+ color: 'var(--color-base-content)',
4564
+ '-x-placeholder-color': 'color-mix(in oklab, var(--color-base-content) 60%, transparent)',
4565
+ flexGrow: '1',
4566
+ flexShrink: '1',
4567
+ },
4568
+ },
4569
+ // The chevron and the × are `<view>`s holding a glyph: centred
4570
+ // in the stretched row (a lynx view lays its child out at the
4571
+ // top), in explicit ink. A held chevron comes up to full ink —
4572
+ // the touch answer to the web's resting 60%. The clear-trigger
4573
+ // declares no pressed flag; its feedback is the text leaving.
4574
+ trigger: {
4575
+ base: { color: 'var(--color-base-content)', display: 'flex', alignItems: 'center', justifyContent: 'center' },
4576
+ states: { pressed: { opacity: '1' } },
4577
+ },
4578
+ 'clear-trigger': {
4579
+ base: { color: 'var(--color-base-content)', display: 'flex', alignItems: 'center', justifyContent: 'center' },
4580
+ },
4581
+ // The chip's ring is the lynx one; its remove button's ring is
4582
+ // drawn inside, so it never paints over the chip's label.
4583
+ tag: { states: lynxFocus() },
4584
+ 'tag-remove': {
4585
+ base: { color: 'var(--color-base-content)' },
4586
+ states: lynxFocus({ inset: true }),
4587
+ },
4588
+ // The popup renders in the overlay outlet, outside the root,
4589
+ // so it cannot inherit `--combobox-accent`, and an unresolved
4590
+ // `var()` on lynx has no fallback (select's
4591
+ // signalxjs/lynx#1168). The popup restates the accent; its
4592
+ // colour-axis twins are in `variants.color` below.
4593
+ popup: { base: { '--combobox-accent': 'var(--color-primary)' } },
4594
+ // A touch list has no pointer highlight: a held option takes
4595
+ // the highlighted wash.
4596
+ item: { states: { pressed: { background: 'var(--color-base-200)' } } },
4597
+ },
4598
+ variants: {
4599
+ color: Object.fromEntries(ROLES.map((c) => [c, { popup: { base: {
4600
+ '--combobox-accent': `var(--color-${c})`,
4601
+ } } }])),
4602
+ },
4603
+ },
4530
4604
  },
4531
4605
  };
4532
4606
  // daisy "btn" that stays pressed: the off state is the neutral btn, the on
@@ -6534,7 +6608,11 @@ export const divider = {
6534
6608
  // no fill, its cross size following the label, a row when
6535
6609
  // horizontal. Both are lynx-zero rendering details, not
6536
6610
  // modifiers an author sets, so they are styled from raw lynx css
6537
- // (the toggle-group join ends' reasoning).
6611
+ // (the toggle-group join ends' reasoning). A segment centres
6612
+ // itself on the label (signalxjs/lynx#1272): it carries the
6613
+ // root's `align-self: stretch`, and a stretched item with a
6614
+ // definite thickness lands at cross-start on lynx — the top of
6615
+ // the label row, not the middle daisy's rules sit on.
6538
6616
  css: `
6539
6617
  .zx-divider__root.zx-m-labelled {
6540
6618
  --divider-ink: transparent;
@@ -6548,6 +6626,7 @@ export const divider = {
6548
6626
  }
6549
6627
  .zx-divider__root.zx-m-segment {
6550
6628
  flex: 1 1 0;
6629
+ align-self: center;
6551
6630
  }
6552
6631
  .zx-divider__root.zx-m-segment.zx-o-horizontal {
6553
6632
  min-width: 0;
@@ -7477,14 +7556,43 @@ export const chat = {
7477
7556
  xl: { bubble: { base: { fontSize: 'var(--text-lg)', padding: 'var(--space-md) var(--space-xl)' } } },
7478
7557
  },
7479
7558
  },
7480
- // The row's vertical padding, restated physically: logical spellings
7481
- // resolve on iOS but not on Android (measured, signalxjs/lynx#1084), so
7482
- // the emitter refuses them.
7559
+ // Lynx (signalxjs/lynx#1276):
7560
+ // - the row's vertical padding, restated physically: logical spellings
7561
+ // resolve on iOS but not on Android (measured, signalxjs/lynx#1084), so
7562
+ // the emitter refuses them;
7563
+ // - lynx has no grid, so the row is a flex column (header, bubble,
7564
+ // footer), gathered to the placement's side. The avatar leaves the
7565
+ // flow: lynx-zero pins it to the row's bottom corner and reserves its
7566
+ // measured width beside the column;
7567
+ // - the `[data-placement] > &` selectors have no class form on the
7568
+ // parts (placement is the root's), so the bubble's square tail corner
7569
+ // is raw lynx css, a descendant of the placed root — the shape the
7570
+ // theme restatements are proven to match. Physical corners: lynx has
7571
+ // no RTL flow.
7483
7572
  targets: {
7484
7573
  lynx: {
7485
7574
  parts: {
7486
- root: { base: { paddingTop: 'var(--space-2xs)', paddingBottom: 'var(--space-2xs)' } },
7575
+ root: {
7576
+ base: {
7577
+ display: 'flex',
7578
+ flexDirection: 'column',
7579
+ alignItems: 'flex-start',
7580
+ paddingTop: 'var(--space-2xs)',
7581
+ paddingBottom: 'var(--space-2xs)',
7582
+ },
7583
+ selectors: {
7584
+ '&[data-placement="end"]': { alignItems: 'flex-end' },
7585
+ },
7586
+ },
7487
7587
  },
7588
+ css: `
7589
+ .zx-chat__root.zx-p-start .zx-chat__bubble {
7590
+ border-bottom-left-radius: 0;
7591
+ }
7592
+ .zx-chat__root.zx-p-end .zx-chat__bubble {
7593
+ border-bottom-right-radius: 0;
7594
+ }
7595
+ `,
7488
7596
  },
7489
7597
  },
7490
7598
  };
@@ -7576,6 +7684,59 @@ export const chatLog = {
7576
7684
  xl: { content: { base: { rowGap: 'var(--space-md)' } }, 'jump-trigger': { base: { '--chat-log-jump-size': 'calc(var(--size-field) * 10)', fontSize: 'var(--text-sm)' } } },
7577
7685
  },
7578
7686
  },
7687
+ // Lynx (signalxjs/lynx#1276). lynx-zero's root is the frame and a native
7688
+ // scroll-view inside Content does the scrolling, so:
7689
+ // - the frame's padding moves onto the content (physical — logical
7690
+ // spellings do not resolve on Android, signalxjs/lynx#1084), so rows
7691
+ // scroll to the frame's edge instead of clipping at an inset;
7692
+ // - the content's grid is a flex column (lynx has no grid); a short
7693
+ // transcript sits at the top — `margin-block-start: auto` has nothing
7694
+ // to push against inside a scroll-view;
7695
+ // - the jump trigger floats in lynx-zero's absolute dock at the frame's
7696
+ // foot, so it drops `position: sticky` and the negative margin, and
7697
+ // restates its inline padding physically;
7698
+ // - `:hover` is dropped on touch: the held trigger shows the hover's
7699
+ // 90% darkening (restated per colour — a colour function over
7700
+ // `--chat-log-fill` cannot bake), with the existing 1px sink;
7701
+ // - the focus rings as `lynxFocus` (lynx#1163), the frame's drawn inside
7702
+ // like the web's negative offset.
7703
+ targets: {
7704
+ lynx: {
7705
+ parts: {
7706
+ root: {
7707
+ base: { padding: '0', overflow: 'hidden' },
7708
+ states: { 'focus-visible': lynxFocusRing('var(--color-base-content)', { inset: true }) },
7709
+ },
7710
+ content: {
7711
+ base: {
7712
+ display: 'flex',
7713
+ flexDirection: 'column',
7714
+ paddingTop: 'var(--space-sm)',
7715
+ paddingBottom: 'var(--space-sm)',
7716
+ paddingLeft: 'var(--space-md)',
7717
+ paddingRight: 'var(--space-md)',
7718
+ },
7719
+ },
7720
+ 'jump-trigger': {
7721
+ base: {
7722
+ position: 'relative',
7723
+ flexDirection: 'row',
7724
+ paddingLeft: 'var(--space-md)',
7725
+ paddingRight: 'var(--space-md)',
7726
+ },
7727
+ states: {
7728
+ pressed: { background: 'color-mix(in oklab, var(--color-primary) 90%, black)' },
7729
+ ...lynxFocus(),
7730
+ },
7731
+ },
7732
+ },
7733
+ variants: {
7734
+ color: Object.fromEntries(ROLES.map((c) => [c, { 'jump-trigger': { states: {
7735
+ pressed: { background: `color-mix(in oklab, var(--color-${c}) 90%, black)` },
7736
+ } } }])),
7737
+ },
7738
+ },
7739
+ },
7579
7740
  };
7580
7741
  /** daisy radial-progress: --value became --progress-percent; same ring. */
7581
7742
  export const radialProgress = {
@@ -7828,13 +7989,26 @@ export const navbar = {
7828
7989
  // so the bar's height ramp is restated as `min-height`; and a lynx flex
7829
7990
  // container is only a row when it says so, so the bar and its three
7830
7991
  // sections spell `flex-direction: row`.
7992
+ //
7993
+ // No section squeezes a word (signalxjs/lynx#1274, zero#499). On the web
7994
+ // `flex: 1 1 0%` is floored by the flex item's automatic minimum (its
7995
+ // min-content width), so "Acme" never breaks. Lynx's flex layout has no
7996
+ // automatic minimum, and its `min-width` takes no intrinsic keyword, so
7997
+ // a zero basis shrank the start below its text and the `<text>` wrapped
7998
+ // per character ("Acm / e"). On lynx the ends start from their content
7999
+ // (`flex-basis: auto`), never shrink, and share the slack equally; the
8000
+ // centre takes daisy's own `flex-shrink: 0`. A bar too narrow for its
8001
+ // content overflows whole, as daisy's does — the btn rule (lynx#1165).
8002
+ // The cost: with a centre and unequal ends, the centre sits off-centre
8003
+ // by half the ends' difference (the web's is exact until a section
8004
+ // reaches its min-content).
7831
8005
  targets: {
7832
8006
  lynx: {
7833
8007
  parts: {
7834
8008
  root: { base: { flexDirection: 'row', minHeight: '4rem' } },
7835
- start: { base: { flexDirection: 'row' } },
7836
- center: { base: { flexDirection: 'row' } },
7837
- end: { base: { flexDirection: 'row' } },
8009
+ start: { base: { flexDirection: 'row', flexBasis: 'auto', flexShrink: '0' } },
8010
+ center: { base: { flexDirection: 'row', flexShrink: '0' } },
8011
+ end: { base: { flexDirection: 'row', flexBasis: 'auto', flexShrink: '0' } },
7838
8012
  },
7839
8013
  variants: {
7840
8014
  size: {
@@ -8767,11 +8941,68 @@ export const drawer = {
8767
8941
  },
8768
8942
  },
8769
8943
  },
8770
- // The btn paddings, restated physically — see `lynxBtnPad` (#1084).
8944
+ // The btn paddings, restated physically — see `lynxBtnPad` (#1084) —
8945
+ // and the btns' press rendering (`lynxBtnPressed`), as dialog wears
8946
+ // them. The edge sheet (signalxjs/lynx#1277): lynx-zero lays the
8947
+ // panel on its edge with flexbox inside the backdrop, so the sheet
8948
+ // stays in flow (`position: relative`, never `fixed`) and sizes to
8949
+ // it — no viewport units, which lynx does not resolve against the
8950
+ // overlay outlet. The skin keeps the cap, the corners and the slide.
8771
8951
  lynx: {
8952
+ keyframes: {
8953
+ // `translate` is Android-asymmetric (#1084): the travel is a
8954
+ // transform function, one per edge.
8955
+ 'zero-daisy-drawer-in-start': 'from { transform: translateX(-100%); } to { transform: translateX(0); }',
8956
+ 'zero-daisy-drawer-in-end': 'from { transform: translateX(100%); } to { transform: translateX(0); }',
8957
+ 'zero-daisy-drawer-in-top': 'from { transform: translateY(-100%); } to { transform: translateY(0); }',
8958
+ 'zero-daisy-drawer-in-bottom': 'from { transform: translateY(100%); } to { transform: translateY(0); }',
8959
+ },
8772
8960
  parts: {
8773
- trigger: { base: lynxBtnPad(4) },
8774
- close: { base: lynxBtnPad(4) },
8961
+ trigger: { base: { ...lynxBtnPad(4), ...lynxBtnFit }, states: { pressed: lynxBtnPressed, ...lynxFocus() } },
8962
+ close: { base: { ...lynxBtnPad(4), ...lynxBtnFit }, states: { pressed: lynxBtnPressed, ...lynxFocus() } },
8963
+ panel: {
8964
+ // The cap alone: `min(20rem, 85vw)` has no lynx spelling
8965
+ // (no min()); lynx-zero states the 85% share inline and
8966
+ // this caps it — together, the web's width.
8967
+ base: { '--l-measure': '20rem' },
8968
+ selectors: {
8969
+ '&[data-l-dock="sheet"]': {
8970
+ position: 'relative',
8971
+ blockSize: 'auto',
8972
+ maxBlockSize: 'none',
8973
+ },
8974
+ // The block edges run full width (the web's `:where()`
8975
+ // pair, one selector each — no `:where()` on lynx),
8976
+ // content-sized up to 85% of the outlet.
8977
+ '&[data-placement="top"]': { '--l-measure': 'none' },
8978
+ '&[data-placement="bottom"]': { '--l-measure': 'none' },
8979
+ '&[data-placement="top"][data-l-dock="sheet"]': {
8980
+ maxBlockSize: '85%',
8981
+ borderBottomLeftRadius: 'var(--radius-box)',
8982
+ borderBottomRightRadius: 'var(--radius-box)',
8983
+ },
8984
+ '&[data-placement="bottom"][data-l-dock="sheet"]': {
8985
+ maxBlockSize: '85%',
8986
+ borderTopLeftRadius: 'var(--radius-box)',
8987
+ borderTopRightRadius: 'var(--radius-box)',
8988
+ },
8989
+ // The slide in from the edge (the web's `translate`
8990
+ // over `@starting-style`, both dropped here). The
8991
+ // exit is an unmount on lynx, so only the entry runs.
8992
+ '&[data-placement="start"][data-l-dock="sheet"][data-state="open"]': {
8993
+ animation: 'zero-daisy-drawer-in-start var(--duration-slow) var(--ease-standard)',
8994
+ },
8995
+ '&[data-placement="end"][data-l-dock="sheet"][data-state="open"]': {
8996
+ animation: 'zero-daisy-drawer-in-end var(--duration-slow) var(--ease-standard)',
8997
+ },
8998
+ '&[data-placement="top"][data-l-dock="sheet"][data-state="open"]': {
8999
+ animation: 'zero-daisy-drawer-in-top var(--duration-slow) var(--ease-standard)',
9000
+ },
9001
+ '&[data-placement="bottom"][data-l-dock="sheet"][data-state="open"]': {
9002
+ animation: 'zero-daisy-drawer-in-bottom var(--duration-slow) var(--ease-standard)',
9003
+ },
9004
+ },
9005
+ },
8775
9006
  },
8776
9007
  variants: { size: lynxBtnSizes('trigger') },
8777
9008
  },
@@ -8970,6 +9201,89 @@ export const table = {
8970
9201
  },
8971
9202
  },
8972
9203
  },
9204
+ // signalxjs/lynx#1279. Lynx has no table layout: lynx-zero lays the
9205
+ // parts out as flex rows itself. The `hover` modifier has no lynx
9206
+ // answer (a touch screen has no hover), nor has the viewport-width
9207
+ // `@media` of the stacked mode — lynx-zero resolves `stack` in JS and
9208
+ // stamps the parts instead (see `css` below).
9209
+ targets: {
9210
+ lynx: {
9211
+ parts: {
9212
+ // The web's `overflow-x: auto` box: a lynx view clips its
9213
+ // rounded frame; a table of fixed columns scrolls in a
9214
+ // scroll-view lynx-zero renders.
9215
+ root: {
9216
+ base: { overflow: 'hidden' },
9217
+ // daisy's ring drawn inside the box, as on the web
9218
+ // (outline-offset: -2px) — spelled as an inset shadow.
9219
+ states: { 'focus-visible': lynxFocusRing('var(--color-base-content)', { inset: true }) },
9220
+ },
9221
+ // The muted header ink: the colour function over
9222
+ // `--table-accent` cannot bake (a recipe-local property),
9223
+ // so the default accent's mix is restated here and each
9224
+ // colour's below.
9225
+ 'header-cell': { base: { color: 'color-mix(in oklab, var(--color-base-content) 60%, transparent)' } },
9226
+ 'cell-label': { base: { color: 'color-mix(in oklab, var(--color-base-content) 60%, transparent)' } },
9227
+ // The web's hover ink, while held; the lynx ring.
9228
+ 'sort-trigger': {
9229
+ base: { flexDirection: 'row' },
9230
+ states: { pressed: { color: 'var(--table-accent)' }, ...lynxFocus() },
9231
+ },
9232
+ },
9233
+ variants: {
9234
+ color: Object.fromEntries(ROLES.map((c) => {
9235
+ const muted = `color-mix(in oklab, ${roleInk(c)} 60%, transparent)`;
9236
+ return [c, {
9237
+ 'header-cell': { base: { color: muted } },
9238
+ 'cell-label': { base: { color: muted } },
9239
+ }];
9240
+ })),
9241
+ },
9242
+ // lynx-zero rendering details, not modifiers an author sets:
9243
+ // - `stripe`: lynx has no `:nth-child`, so the body stamps its
9244
+ // even, unselected rows (mount order) under `zebra`.
9245
+ // - `held`: the unsorted mark the web reveals under a hovered or
9246
+ // keyboard-focused trigger, shown while the trigger is held.
9247
+ // - `stacked`: the stacked mode's card chrome (the web's
9248
+ // below-breakpoint rules). Zero widths and paddings keep a
9249
+ // var() so they beat the var-bearing base values (lynx expands
9250
+ // var() declarations after the cascade, signalxjs/lynx#1161);
9251
+ // the root keeps its base-100 fill (a var-free transparent
9252
+ // would lose the same way).
9253
+ css: `
9254
+ .zx-table__root.zx-m-stacked {
9255
+ border-width: calc(var(--border) * 0);
9256
+ border-radius: calc(var(--radius-box) * 0);
9257
+ }
9258
+ .zx-table__caption.zx-m-stacked {
9259
+ padding-left: calc(var(--table-pad-inline) * 0);
9260
+ padding-right: calc(var(--table-pad-inline) * 0);
9261
+ }
9262
+ .zx-table__row.zx-m-stacked {
9263
+ border: var(--border) solid var(--color-base-200);
9264
+ border-radius: var(--radius-box);
9265
+ background: var(--color-base-100);
9266
+ padding: var(--space-sm) var(--table-pad-inline);
9267
+ margin-bottom: var(--space-md);
9268
+ }
9269
+ .zx-table__row.zx-m-stacked.zx-f-selected {
9270
+ background: var(--color-base-300);
9271
+ }
9272
+ .zx-table__cell.zx-m-stacked {
9273
+ padding-left: calc(var(--table-pad-inline) * 0);
9274
+ padding-right: calc(var(--table-pad-inline) * 0);
9275
+ padding-top: var(--space-xs);
9276
+ padding-bottom: var(--space-xs);
9277
+ }
9278
+ .zx-table__row.zx-m-stripe {
9279
+ background: var(--color-base-200);
9280
+ }
9281
+ .zx-table__sort-indicator.zx-m-held.zx-s-none {
9282
+ opacity: 0.6;
9283
+ }
9284
+ `,
9285
+ },
9286
+ },
8973
9287
  };
8974
9288
  /**
8975
9289
  * FileUpload — daisy's file-input family reshaped for the composed anatomy:
@@ -9135,6 +9449,63 @@ export const fileUpload = {
9135
9449
  xl: { root: { base: { '--fu-pad': 'calc(var(--space-xl) * 1.25)', '--fu-font': 'var(--text-md)' } } },
9136
9450
  },
9137
9451
  },
9452
+ // Lynx (signalxjs/lynx#1276):
9453
+ // - lynx has no grid: the root and the item list are flex columns, and
9454
+ // the stretched parts (dropzone, item list) say so with `align-self`;
9455
+ // the rows (trigger, item) state `flex-direction: row`;
9456
+ // - the dropzone centres its words in a column (lynx text alignment is
9457
+ // the text's own), and its highlighted wash — a colour function over
9458
+ // `--fu-accent`, which cannot bake — is restated per colour over the
9459
+ // role. lynx never drives `highlighted` (no drag source); it shows
9460
+ // through `ForceStates` in the gallery;
9461
+ // - `:hover` is dropped on touch: the held trigger shows daisy's
9462
+ // base-300 wash + 1px sink (`lynxBtnPressed`, in place of the
9463
+ // standalone `translate`, which Android does not resolve), and the
9464
+ // held × and clear show the ghost's base-200 wash;
9465
+ // - the focus rings as `lynxFocus` (lynx#1163).
9466
+ targets: {
9467
+ lynx: {
9468
+ parts: {
9469
+ root: { base: { display: 'flex', flexDirection: 'column', alignItems: 'flex-start' } },
9470
+ trigger: {
9471
+ base: { flexDirection: 'row' },
9472
+ states: { pressed: lynxBtnPressed, ...lynxFocus() },
9473
+ },
9474
+ dropzone: {
9475
+ base: { alignSelf: 'stretch', display: 'flex', flexDirection: 'column', alignItems: 'center' },
9476
+ states: {
9477
+ highlighted: { background: 'color-mix(in oklab, var(--color-primary) 8%, var(--color-base-100))' },
9478
+ },
9479
+ },
9480
+ 'item-group': {
9481
+ base: { alignSelf: 'stretch', display: 'flex', flexDirection: 'column' },
9482
+ },
9483
+ item: { base: { flexDirection: 'row' } },
9484
+ 'item-remove': {
9485
+ states: { pressed: { background: 'var(--color-base-200)' }, ...lynxFocus() },
9486
+ },
9487
+ 'clear-trigger': {
9488
+ states: { pressed: { background: 'var(--color-base-200)' }, ...lynxFocus() },
9489
+ },
9490
+ },
9491
+ variants: {
9492
+ color: Object.fromEntries(ROLES.map((c) => [c, { dropzone: { states: {
9493
+ highlighted: { background: `color-mix(in oklab, var(--color-${c}) 8%, var(--color-base-100))` },
9494
+ } } }])),
9495
+ },
9496
+ },
9497
+ },
9498
+ };
9499
+ /** A carousel nav circle on lynx: the glyph centred as flex (no `grid`). */
9500
+ const carouselTriggerLynx = {
9501
+ display: 'flex',
9502
+ alignItems: 'center',
9503
+ justifyContent: 'center',
9504
+ };
9505
+ /** A held carousel nav circle on lynx: daisy's hover wash plus the 1px sink, and the lynx ring. */
9506
+ const carouselTriggerLynxStates = {
9507
+ pressed: { background: 'var(--color-base-300)', transform: 'translateY(1px)' },
9508
+ ...lynxFocus(),
9138
9509
  };
9139
9510
  /**
9140
9511
  * Carousel — daisy's carousel is exactly a scroll-snap box; the additions
@@ -9286,14 +9657,60 @@ export const carousel = {
9286
9657
  // spellings resolve on iOS but not on Android (measured,
9287
9658
  // signalxjs/lynx#1084), so the emitter refuses them. Physical is the
9288
9659
  // lynx target's norm — no RTL flow there, so `start` IS left.
9660
+ //
9661
+ // signalxjs/lynx#1279 — the rest of the lynx shape:
9662
+ // - `grid` does not lay out on lynx: the root is a flex column, and a
9663
+ // trigger centres its glyph as flex.
9664
+ // - The dot: the web draws it on `::before` inside a
9665
+ // `max(dot, 1.5rem)` button; lynx has neither pseudo-elements nor
9666
+ // `max()`, so lynx-zero renders the dot AS the indicator (its touch
9667
+ // area widened with `hit-slop`) and the ring and the active fill ride
9668
+ // the part.
9669
+ // - The web sinks a held trigger with the standalone `translate`,
9670
+ // which Android ignores (#1084): a transform function here, over
9671
+ // daisy's hover wash (no hover on touch).
9672
+ // - Rings: lynx's outline ignores radius and has no offset (#1163).
9673
+ // No replacement for the viewport's `:focus-visible` ring: there is no
9674
+ // keyboard focus on lynx, and the part declares no flag to key it on.
9289
9675
  targets: {
9290
9676
  lynx: {
9291
9677
  parts: {
9678
+ root: { base: { display: 'flex', flexDirection: 'column' } },
9292
9679
  'prev-trigger': {
9293
- base: { top: 'calc(50% - var(--carousel-nav) / 2)', left: 'var(--space-sm)' },
9680
+ base: {
9681
+ top: 'calc(50% - var(--carousel-nav) / 2)',
9682
+ left: 'var(--space-sm)',
9683
+ ...carouselTriggerLynx,
9684
+ },
9685
+ states: carouselTriggerLynxStates,
9294
9686
  },
9295
9687
  'next-trigger': {
9296
- base: { top: 'calc(50% - var(--carousel-nav) / 2)', right: 'var(--space-sm)' },
9688
+ base: {
9689
+ top: 'calc(50% - var(--carousel-nav) / 2)',
9690
+ right: 'var(--space-sm)',
9691
+ ...carouselTriggerLynx,
9692
+ },
9693
+ states: carouselTriggerLynxStates,
9694
+ },
9695
+ 'indicator-group': { base: { flexDirection: 'row', alignItems: 'center' } },
9696
+ indicator: {
9697
+ base: {
9698
+ display: 'flex',
9699
+ width: 'var(--carousel-dot)',
9700
+ height: 'var(--carousel-dot)',
9701
+ flexShrink: '0',
9702
+ // Longhands: the ring's colour bakes per theme only
9703
+ // on its own (a shorthand mixing it with the
9704
+ // --border calc cannot).
9705
+ borderWidth: 'calc(var(--border) * 2)',
9706
+ borderStyle: 'solid',
9707
+ borderColor: 'color-mix(in oklab, var(--color-base-content) 70%, transparent)',
9708
+ borderRadius: '9999px',
9709
+ },
9710
+ states: {
9711
+ active: { background: 'var(--carousel-accent)', borderColor: 'var(--carousel-accent)' },
9712
+ ...lynxFocus(),
9713
+ },
9297
9714
  },
9298
9715
  },
9299
9716
  },