@sigx/zero-daisyui 0.8.0 → 0.10.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.
Files changed (40) hide show
  1. package/README.md +3 -1
  2. package/dist/audit.json +55 -0
  3. package/dist/components.d.ts +9 -0
  4. package/dist/components.js +1 -0
  5. package/dist/css/components/avatar-group.css +168 -0
  6. package/dist/css/components/drawer.css +42 -6
  7. package/dist/css/index.css +209 -6
  8. package/dist/lynx/components/avatar-group.css +97 -0
  9. package/dist/lynx/components/button.css +2 -2
  10. package/dist/lynx/components/carousel.css +10 -10
  11. package/dist/lynx/components/checkbox.css +7 -7
  12. package/dist/lynx/components/combobox.css +2 -2
  13. package/dist/lynx/components/dialog.css +2 -2
  14. package/dist/lynx/components/diff.css +10 -10
  15. package/dist/lynx/components/divider.css +19 -0
  16. package/dist/lynx/components/drawer.css +24 -2
  17. package/dist/lynx/components/grid.css +1 -1
  18. package/dist/lynx/components/hover-card.css +1 -1
  19. package/dist/lynx/components/menu.css +2 -2
  20. package/dist/lynx/components/navbar.css +5 -5
  21. package/dist/lynx/components/number-input.css +1 -1
  22. package/dist/lynx/components/popover.css +1 -1
  23. package/dist/lynx/components/radio-group.css +6 -6
  24. package/dist/lynx/components/select.css +39 -10
  25. package/dist/lynx/components/slider.css +2 -2
  26. package/dist/lynx/components/tabs.css +1 -1
  27. package/dist/lynx/components/toast.css +2 -2
  28. package/dist/lynx/components/tooltip.css +1 -1
  29. package/dist/lynx/index.css +350 -182
  30. package/dist/lynx/manifest.json +30 -3
  31. package/dist/lynx/tokens.css +114 -114
  32. package/dist/manifest.json +28 -1
  33. package/dist/recipes.d.ts +1 -0
  34. package/dist/recipes.d.ts.map +1 -1
  35. package/dist/recipes.js +208 -13
  36. package/dist/recipes.js.map +1 -1
  37. package/dist/register.d.ts +9 -0
  38. package/dist/report.json +383 -16
  39. package/package.json +4 -4
  40. package/src/recipes.ts +212 -13
package/dist/recipes.js CHANGED
@@ -2851,6 +2851,36 @@ const fieldControl = {
2851
2851
  * a part inside the trigger can make room for the button laid over it.
2852
2852
  */
2853
2853
  const SELECT_CLEARABLE = '[data-scope="select"][data-part="root"]:has(> [data-scope="select"][data-part="clear-trigger"]) &';
2854
+ /**
2855
+ * The select trigger's lynx steps — `[inline padding in --size-field units,
2856
+ * font-size step]` — as the size variants set them (`lynxBtnPad` and the
2857
+ * web ramp's `fontSize`). One table, so the clear-trigger's offset below
2858
+ * cannot drift from the trigger it sits in.
2859
+ */
2860
+ const SELECT_LYNX_STEPS = {
2861
+ xs: [2, 'xs'],
2862
+ sm: [3, 'sm'],
2863
+ md: [4, 'sm'],
2864
+ lg: [5, 'md'],
2865
+ xl: [6, 'lg'],
2866
+ };
2867
+ /**
2868
+ * Where the lynx clear-trigger's 1.5rem chip sits at one size step
2869
+ * (signalxjs/lynx#1184): centred in the field — the root is exactly the
2870
+ * trigger's height, so half the field less half the chip, from the top —
2871
+ * and one `--space-xs` short of the chevron's 1em box, which sits inside the
2872
+ * trigger's border and end padding at that step's font size. Physical
2873
+ * `top`/`right` and direct `calc(var())` only: lynx resolves no logical
2874
+ * insets on Android and no `min()`, and drops a `var()` that holds a
2875
+ * `calc()`.
2876
+ */
2877
+ const lynxSelectClear = (step) => {
2878
+ const [pad, text] = SELECT_LYNX_STEPS[step];
2879
+ return {
2880
+ top: `calc(var(--size-field) * ${FIELD_STEPS[step] / 2} - 0.75rem)`,
2881
+ right: `calc(var(--border) + var(--size-field) * ${pad} + var(--text-${text}) + var(--space-xs))`,
2882
+ };
2883
+ };
2854
2884
  export const select = {
2855
2885
  component: 'select',
2856
2886
  // Accent as text/border ink only — daisy's highlighted item is a neutral
@@ -3056,9 +3086,23 @@ export const select = {
3056
3086
  // A touch list has no highlight: the pressed item takes the
3057
3087
  // highlighted item's wash.
3058
3088
  item: { states: { pressed: { background: 'var(--color-base-200)' } } },
3089
+ // The × and the ▾ get a spacing contract (signalxjs/lynx#1184).
3090
+ // The web offsets the clear-trigger by "the md padding + 1em",
3091
+ // and the 1em is the clear-trigger's own text-sm: at lg/xl the
3092
+ // trigger's padding and chevron both grow, so the × slid onto
3093
+ // the ▾. Here the chevron is a 1em box (right-aligned, so an
3094
+ // unclearable select looks as before) and the clear-trigger a
3095
+ // 1.5rem square (WCAG 2.5.8's target) placed per size beside
3096
+ // it — see `lynxSelectClear`. The web's `min()` height and
3097
+ // `margin-block: auto` centring are dropped on lynx, which
3098
+ // left the box stretched to the field's full height: its
3099
+ // focus ring was a tall pill. The ring is inset, so it hugs
3100
+ // the chip and can never reach the chevron, and no gap shadow
3101
+ // paints past the chip's rounded corners.
3102
+ indicator: { base: { width: '1em', textAlign: 'right' } },
3059
3103
  'clear-trigger': {
3060
- base: { top: 'var(--space-xs)', bottom: 'var(--space-xs)', right: 'calc(var(--size-field) * 4 + 1em + var(--space-xs))', minWidth: '1.5rem' },
3061
- states: lynxFocus(),
3104
+ base: { ...lynxSelectClear('md'), width: '1.5rem', height: '1.5rem', minWidth: '1.5rem', boxSizing: 'border-box' },
3105
+ states: lynxFocus({ inset: true }),
3062
3106
  },
3063
3107
  },
3064
3108
  variants: {
@@ -3067,7 +3111,10 @@ export const select = {
3067
3111
  color: Object.fromEntries(ROLES.map((c) => [c, { popup: { base: {
3068
3112
  '--select-accent': `var(--color-${c})`,
3069
3113
  } } }])),
3070
- size: { ...lynxBtnSizes('trigger'), md: { trigger: { base: lynxBtnPad(4) } } },
3114
+ size: Object.fromEntries(Object.keys(SELECT_LYNX_STEPS).map((step) => [step, {
3115
+ trigger: { base: lynxBtnPad(SELECT_LYNX_STEPS[step][0]) },
3116
+ 'clear-trigger': { base: lynxSelectClear(step) },
3117
+ }])),
3071
3118
  },
3072
3119
  },
3073
3120
  },
@@ -3501,6 +3548,98 @@ export const avatar = {
3501
3548
  },
3502
3549
  },
3503
3550
  };
3551
+ /**
3552
+ * Avatar group (#297) — daisy's `avatar-group`: the faces overlap by a
3553
+ * quarter, each already cut out by the avatar's own base-100 gap ring, and the
3554
+ * "+N" chip is daisy's `avatar-placeholder` (neutral fill, neutral-content
3555
+ * ink, a circle) wearing the same ring. The group's `size` borrows the
3556
+ * avatar's own size step (`composes`), so a group sizes its faces without a
3557
+ * prop on each, and an avatar's own `size` still wins. Colour is daisy's
3558
+ * ring colour: it rings the chip, and it is borrowed by the avatars too, so
3559
+ * one `color` on the group rings every face alike.
3560
+ */
3561
+ const avatarGroupSteps = {
3562
+ xs: ['calc(var(--size-selector) * 6)', 'var(--text-xs)'],
3563
+ sm: ['calc(var(--size-selector) * 8)', 'var(--text-xs)'],
3564
+ lg: ['calc(var(--size-selector) * 12)', 'var(--text-md)'],
3565
+ xl: ['calc(var(--size-selector) * 16)', 'var(--text-lg)'],
3566
+ };
3567
+ export const avatarGroup = {
3568
+ component: 'avatar-group',
3569
+ tokens: {
3570
+ '--avatar-group-size': 'calc(var(--size-selector) * 10)',
3571
+ '--avatar-group-text': 'var(--text-sm)',
3572
+ '--avatar-group-ring': 'var(--color-primary)',
3573
+ },
3574
+ parts: {
3575
+ root: {
3576
+ base: {
3577
+ display: 'inline-flex',
3578
+ alignItems: 'center',
3579
+ verticalAlign: 'middle',
3580
+ isolation: 'isolate',
3581
+ },
3582
+ },
3583
+ overflow: {
3584
+ base: {
3585
+ // Positioned like the avatars, or it would paint under the
3586
+ // face it overlaps.
3587
+ position: 'relative',
3588
+ display: 'inline-grid',
3589
+ placeItems: 'center',
3590
+ boxSizing: 'border-box',
3591
+ minWidth: 'var(--avatar-group-size)',
3592
+ height: 'var(--avatar-group-size)',
3593
+ paddingInline: 'var(--space-2xs)',
3594
+ marginInlineStart: 'calc(var(--avatar-group-size) * -0.25)',
3595
+ borderRadius: '9999px',
3596
+ boxShadow: '0 0 0 2px var(--color-base-100), 0 0 0 4px var(--avatar-group-ring)',
3597
+ background: 'var(--color-neutral)',
3598
+ color: 'var(--color-neutral-content)',
3599
+ fontSize: 'var(--avatar-group-text)',
3600
+ fontWeight: 'var(--weight-semibold)',
3601
+ fontVariantNumeric: 'tabular-nums',
3602
+ whiteSpace: 'nowrap',
3603
+ userSelect: 'none',
3604
+ },
3605
+ },
3606
+ },
3607
+ composes: {
3608
+ avatar: {
3609
+ parts: {
3610
+ root: {
3611
+ selectors: {
3612
+ '&:not(:first-child)': { marginInlineStart: 'calc(var(--avatar-group-size) * -0.25)' },
3613
+ },
3614
+ },
3615
+ },
3616
+ },
3617
+ },
3618
+ compoundVariants: [
3619
+ ...Object.keys(avatarGroupSteps).map((size) => ({
3620
+ match: { size },
3621
+ parts: {},
3622
+ composes: { avatar: { axes: { size } } },
3623
+ })),
3624
+ ...ROLES.map((color) => ({
3625
+ match: { color },
3626
+ parts: {},
3627
+ composes: { avatar: { axes: { color } } },
3628
+ })),
3629
+ ],
3630
+ variants: {
3631
+ color: Object.fromEntries(ROLES.map((c) => [c, { root: { base: {
3632
+ '--avatar-group-ring': `var(--color-${c})`,
3633
+ } } }])),
3634
+ size: {
3635
+ ...Object.fromEntries(Object.entries(avatarGroupSteps).map(([size, [box, text]]) => [size, { root: { base: {
3636
+ '--avatar-group-size': box, '--avatar-group-text': text,
3637
+ } } }])),
3638
+ // `md` is the un-attributed render — the defaults in `tokens:`.
3639
+ md: {},
3640
+ },
3641
+ },
3642
+ };
3504
3643
  /**
3505
3644
  * A toast whose indicator is rendered (#292): the grid grows a leading column
3506
3645
  * for the mark, and the text, action and close step one column along.
@@ -5402,6 +5541,25 @@ export const divider = {
5402
5541
  xl: { root: { base: { '--divider-thickness': 'calc(var(--border) * 3)' } } },
5403
5542
  },
5404
5543
  },
5544
+ targets: {
5545
+ lynx: {
5546
+ parts: {
5547
+ // Lynx drops the ::before/::after segments the rule is drawn
5548
+ // with above, which left the lynx divider with no line and,
5549
+ // since only those rules read `--divider-thickness`, no size
5550
+ // ramp either (#375). There the root itself is the line, as
5551
+ // it was before the segments (#356): filled with the ink and
5552
+ // one thickness across.
5553
+ root: {
5554
+ base: { background: 'var(--divider-ink)' },
5555
+ selectors: {
5556
+ '&[data-orientation="horizontal"]': { blockSize: 'var(--divider-thickness)' },
5557
+ '&[data-orientation="vertical"]': { inlineSize: 'var(--divider-thickness)' },
5558
+ },
5559
+ },
5560
+ },
5561
+ },
5562
+ },
5405
5563
  };
5406
5564
  // ── Loading (#314) ────────────────────────────────────────────────────────
5407
5565
  /**
@@ -7076,9 +7234,11 @@ export const steps = {
7076
7234
  /**
7077
7235
  * The modal sheet's slide (#83): in from its edge, back out to it.
7078
7236
  *
7079
- * `translate` is physical, so the travel is a custom property that flips with
7080
- * the placement AND the direction — off the reading start is leftward in LTR
7081
- * and rightward in RTL (the `rtl` hedge, as everywhere here). Keyed on
7237
+ * `translate` is physical, so the travel is a custom property — the whole
7238
+ * `x y` pair — that flips with the placement AND the direction: off the
7239
+ * reading start is leftward in LTR and rightward in RTL (the `rtl` hedge, as
7240
+ * everywhere here), while a `top` / `bottom` sheet travels on Y and mirrors
7241
+ * in neither (#291). Keyed on
7082
7242
  * `data-l-dock="sheet"`, the regime, which holds through the exit where
7083
7243
  * `:modal` does not, so the slide-out leaves from the sheet's own box.
7084
7244
  * Opacity stays at 1: the travel is the transition. Each direction rides the
@@ -7092,16 +7252,19 @@ const sheetSlide = (enter, exit) => {
7092
7252
  return `translate ${tempo}, display ${duration} allow-discrete, overlay ${duration} allow-discrete`;
7093
7253
  };
7094
7254
  return {
7095
- base: { '--drawer-travel': '-100%' },
7255
+ base: { '--drawer-travel': '-100% 0' },
7096
7256
  selectors: {
7097
- '&[data-placement="end"]': { '--drawer-travel': '100%' },
7098
- [`&[data-placement="start"]${rtl}`]: { '--drawer-travel': '100%' },
7099
- [`&[data-placement="end"]${rtl}`]: { '--drawer-travel': '-100%' },
7100
- [sheet]: { opacity: '1', translate: 'var(--drawer-travel) 0', transition: travel(exit) },
7257
+ '&[data-placement="end"]': { '--drawer-travel': '100% 0' },
7258
+ [`&[data-placement="start"]${rtl}`]: { '--drawer-travel': '100% 0' },
7259
+ [`&[data-placement="end"]${rtl}`]: { '--drawer-travel': '-100% 0' },
7260
+ // The block edges travel on Y, and no direction mirrors them (#291).
7261
+ '&[data-placement="top"]': { '--drawer-travel': '0 -100%' },
7262
+ '&[data-placement="bottom"]': { '--drawer-travel': '0 100%' },
7263
+ [sheet]: { opacity: '1', translate: 'var(--drawer-travel)', transition: travel(exit) },
7101
7264
  [open]: { translate: 'none', transition: travel(enter) },
7102
7265
  },
7103
7266
  at: {
7104
- 'starting-style': { selectors: { [open]: { opacity: '1', translate: 'var(--drawer-travel) 0' } } },
7267
+ 'starting-style': { selectors: { [open]: { opacity: '1', translate: 'var(--drawer-travel)' } } },
7105
7268
  'reduced-motion': { selectors: { [sheet]: { transition: 'none' }, [open]: { transition: 'none' } } },
7106
7269
  },
7107
7270
  };
@@ -7167,6 +7330,38 @@ export const drawer = {
7167
7330
  },
7168
7331
  '&[data-placement="start"][data-l-dock="sheet"]': { insetInlineStart: '0', insetInlineEnd: 'auto' },
7169
7332
  '&[data-placement="end"][data-l-dock="sheet"]': { insetInlineStart: 'auto', insetInlineEnd: '0' },
7333
+ /**
7334
+ * The block edges (#291): a sheet across the viewport's width,
7335
+ * pinned with `inset-block-*` — nothing here mirrors in RTL. Its
7336
+ * height is this recipe's: content-sized up to most of the
7337
+ * viewport, so the scrim stays in reach. Full width by default —
7338
+ * `measure` still caps the INLINE size (centred by the auto
7339
+ * margins), which the `:where()` keeps below the layout step
7340
+ * table's specificity whatever order the files load in.
7341
+ */
7342
+ '&:where([data-placement="top"], [data-placement="bottom"])': { '--l-measure': 'none' },
7343
+ '&[data-placement="top"][data-l-dock="sheet"]': {
7344
+ insetBlockStart: '0',
7345
+ insetBlockEnd: 'auto',
7346
+ insetInlineStart: '0',
7347
+ insetInlineEnd: '0',
7348
+ marginInline: 'auto',
7349
+ blockSize: 'auto',
7350
+ maxBlockSize: '85dvh',
7351
+ borderEndStartRadius: 'var(--radius-box)',
7352
+ borderEndEndRadius: 'var(--radius-box)',
7353
+ },
7354
+ '&[data-placement="bottom"][data-l-dock="sheet"]': {
7355
+ insetBlockStart: 'auto',
7356
+ insetBlockEnd: '0',
7357
+ insetInlineStart: '0',
7358
+ insetInlineEnd: '0',
7359
+ marginInline: 'auto',
7360
+ blockSize: 'auto',
7361
+ maxBlockSize: '85dvh',
7362
+ borderStartStartRadius: 'var(--radius-box)',
7363
+ borderStartEndRadius: 'var(--radius-box)',
7364
+ },
7170
7365
  },
7171
7366
  }),
7172
7367
  backdrop: {
@@ -7992,7 +8187,7 @@ export const diff = {
7992
8187
  };
7993
8188
  export const recipes = [
7994
8189
  tabs, collapsible, switchRecipe, dialog, popover, tooltip, hoverCard, menu, menubar,
7995
- field, fieldset, checkbox, checkboxGroup, radioGroup, progress, slider, accordion, select, button, avatar, toast, combobox,
8190
+ field, fieldset, checkbox, checkboxGroup, radioGroup, progress, slider, accordion, select, button, avatar, avatarGroup, toast, combobox,
7996
8191
  toggle, toggleGroup, numberInput, ratingGroup, treeView, input, textarea,
7997
8192
  card, alert, emptyState, badge, divider, skeleton, spinner,
7998
8193
  kbd, status, indicator, stats, timeline, chat, chatLog, radialProgress, join,