@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.
- package/README.md +3 -1
- package/dist/audit.json +55 -0
- package/dist/components.d.ts +9 -0
- package/dist/components.js +1 -0
- package/dist/css/components/avatar-group.css +168 -0
- package/dist/css/components/drawer.css +42 -6
- package/dist/css/index.css +209 -6
- package/dist/lynx/components/avatar-group.css +97 -0
- package/dist/lynx/components/button.css +2 -2
- package/dist/lynx/components/carousel.css +10 -10
- package/dist/lynx/components/checkbox.css +7 -7
- package/dist/lynx/components/combobox.css +2 -2
- package/dist/lynx/components/dialog.css +2 -2
- package/dist/lynx/components/diff.css +10 -10
- package/dist/lynx/components/divider.css +19 -0
- package/dist/lynx/components/drawer.css +24 -2
- package/dist/lynx/components/grid.css +1 -1
- package/dist/lynx/components/hover-card.css +1 -1
- package/dist/lynx/components/menu.css +2 -2
- package/dist/lynx/components/navbar.css +5 -5
- package/dist/lynx/components/number-input.css +1 -1
- package/dist/lynx/components/popover.css +1 -1
- package/dist/lynx/components/radio-group.css +6 -6
- package/dist/lynx/components/select.css +39 -10
- package/dist/lynx/components/slider.css +2 -2
- package/dist/lynx/components/tabs.css +1 -1
- package/dist/lynx/components/toast.css +2 -2
- package/dist/lynx/components/tooltip.css +1 -1
- package/dist/lynx/index.css +350 -182
- package/dist/lynx/manifest.json +30 -3
- package/dist/lynx/tokens.css +114 -114
- package/dist/manifest.json +28 -1
- package/dist/recipes.d.ts +1 -0
- package/dist/recipes.d.ts.map +1 -1
- package/dist/recipes.js +208 -13
- package/dist/recipes.js.map +1 -1
- package/dist/register.d.ts +9 -0
- package/dist/report.json +383 -16
- package/package.json +4 -4
- package/src/recipes.ts +212 -13
package/src/recipes.ts
CHANGED
|
@@ -2939,6 +2939,38 @@ const fieldControl: NonNullable<PartStyles['base']> = {
|
|
|
2939
2939
|
*/
|
|
2940
2940
|
const SELECT_CLEARABLE = '[data-scope="select"][data-part="root"]:has(> [data-scope="select"][data-part="clear-trigger"]) &';
|
|
2941
2941
|
|
|
2942
|
+
/**
|
|
2943
|
+
* The select trigger's lynx steps — `[inline padding in --size-field units,
|
|
2944
|
+
* font-size step]` — as the size variants set them (`lynxBtnPad` and the
|
|
2945
|
+
* web ramp's `fontSize`). One table, so the clear-trigger's offset below
|
|
2946
|
+
* cannot drift from the trigger it sits in.
|
|
2947
|
+
*/
|
|
2948
|
+
const SELECT_LYNX_STEPS = {
|
|
2949
|
+
xs: [2, 'xs'],
|
|
2950
|
+
sm: [3, 'sm'],
|
|
2951
|
+
md: [4, 'sm'],
|
|
2952
|
+
lg: [5, 'md'],
|
|
2953
|
+
xl: [6, 'lg'],
|
|
2954
|
+
} as const satisfies Record<keyof typeof FIELD_STEPS, readonly [number, string]>;
|
|
2955
|
+
|
|
2956
|
+
/**
|
|
2957
|
+
* Where the lynx clear-trigger's 1.5rem chip sits at one size step
|
|
2958
|
+
* (signalxjs/lynx#1184): centred in the field — the root is exactly the
|
|
2959
|
+
* trigger's height, so half the field less half the chip, from the top —
|
|
2960
|
+
* and one `--space-xs` short of the chevron's 1em box, which sits inside the
|
|
2961
|
+
* trigger's border and end padding at that step's font size. Physical
|
|
2962
|
+
* `top`/`right` and direct `calc(var())` only: lynx resolves no logical
|
|
2963
|
+
* insets on Android and no `min()`, and drops a `var()` that holds a
|
|
2964
|
+
* `calc()`.
|
|
2965
|
+
*/
|
|
2966
|
+
const lynxSelectClear = (step: keyof typeof SELECT_LYNX_STEPS): NonNullable<PartStyles['base']> => {
|
|
2967
|
+
const [pad, text] = SELECT_LYNX_STEPS[step];
|
|
2968
|
+
return {
|
|
2969
|
+
top: `calc(var(--size-field) * ${FIELD_STEPS[step] / 2} - 0.75rem)`,
|
|
2970
|
+
right: `calc(var(--border) + var(--size-field) * ${pad} + var(--text-${text}) + var(--space-xs))`,
|
|
2971
|
+
};
|
|
2972
|
+
};
|
|
2973
|
+
|
|
2942
2974
|
export const select: RecipeInput = {
|
|
2943
2975
|
component: 'select',
|
|
2944
2976
|
// Accent as text/border ink only — daisy's highlighted item is a neutral
|
|
@@ -3144,9 +3176,23 @@ export const select: RecipeInput = {
|
|
|
3144
3176
|
// A touch list has no highlight: the pressed item takes the
|
|
3145
3177
|
// highlighted item's wash.
|
|
3146
3178
|
item: { states: { pressed: { background: 'var(--color-base-200)' } } },
|
|
3179
|
+
// The × and the ▾ get a spacing contract (signalxjs/lynx#1184).
|
|
3180
|
+
// The web offsets the clear-trigger by "the md padding + 1em",
|
|
3181
|
+
// and the 1em is the clear-trigger's own text-sm: at lg/xl the
|
|
3182
|
+
// trigger's padding and chevron both grow, so the × slid onto
|
|
3183
|
+
// the ▾. Here the chevron is a 1em box (right-aligned, so an
|
|
3184
|
+
// unclearable select looks as before) and the clear-trigger a
|
|
3185
|
+
// 1.5rem square (WCAG 2.5.8's target) placed per size beside
|
|
3186
|
+
// it — see `lynxSelectClear`. The web's `min()` height and
|
|
3187
|
+
// `margin-block: auto` centring are dropped on lynx, which
|
|
3188
|
+
// left the box stretched to the field's full height: its
|
|
3189
|
+
// focus ring was a tall pill. The ring is inset, so it hugs
|
|
3190
|
+
// the chip and can never reach the chevron, and no gap shadow
|
|
3191
|
+
// paints past the chip's rounded corners.
|
|
3192
|
+
indicator: { base: { width: '1em', textAlign: 'right' } },
|
|
3147
3193
|
'clear-trigger': {
|
|
3148
|
-
base: {
|
|
3149
|
-
states: lynxFocus(),
|
|
3194
|
+
base: { ...lynxSelectClear('md'), width: '1.5rem', height: '1.5rem', minWidth: '1.5rem', boxSizing: 'border-box' },
|
|
3195
|
+
states: lynxFocus({ inset: true }),
|
|
3150
3196
|
},
|
|
3151
3197
|
},
|
|
3152
3198
|
variants: {
|
|
@@ -3155,7 +3201,10 @@ export const select: RecipeInput = {
|
|
|
3155
3201
|
color: Object.fromEntries(ROLES.map((c) => [c, { popup: { base: {
|
|
3156
3202
|
'--select-accent': `var(--color-${c})`,
|
|
3157
3203
|
} } }])),
|
|
3158
|
-
size:
|
|
3204
|
+
size: Object.fromEntries((Object.keys(SELECT_LYNX_STEPS) as (keyof typeof SELECT_LYNX_STEPS)[]).map((step) => [step, {
|
|
3205
|
+
trigger: { base: lynxBtnPad(SELECT_LYNX_STEPS[step][0]) },
|
|
3206
|
+
'clear-trigger': { base: lynxSelectClear(step) },
|
|
3207
|
+
}])),
|
|
3159
3208
|
},
|
|
3160
3209
|
},
|
|
3161
3210
|
},
|
|
@@ -3599,6 +3648,100 @@ export const avatar: RecipeInput = {
|
|
|
3599
3648
|
},
|
|
3600
3649
|
};
|
|
3601
3650
|
|
|
3651
|
+
/**
|
|
3652
|
+
* Avatar group (#297) — daisy's `avatar-group`: the faces overlap by a
|
|
3653
|
+
* quarter, each already cut out by the avatar's own base-100 gap ring, and the
|
|
3654
|
+
* "+N" chip is daisy's `avatar-placeholder` (neutral fill, neutral-content
|
|
3655
|
+
* ink, a circle) wearing the same ring. The group's `size` borrows the
|
|
3656
|
+
* avatar's own size step (`composes`), so a group sizes its faces without a
|
|
3657
|
+
* prop on each, and an avatar's own `size` still wins. Colour is daisy's
|
|
3658
|
+
* ring colour: it rings the chip, and it is borrowed by the avatars too, so
|
|
3659
|
+
* one `color` on the group rings every face alike.
|
|
3660
|
+
*/
|
|
3661
|
+
const avatarGroupSteps: Record<string, [string, string]> = {
|
|
3662
|
+
xs: ['calc(var(--size-selector) * 6)', 'var(--text-xs)'],
|
|
3663
|
+
sm: ['calc(var(--size-selector) * 8)', 'var(--text-xs)'],
|
|
3664
|
+
lg: ['calc(var(--size-selector) * 12)', 'var(--text-md)'],
|
|
3665
|
+
xl: ['calc(var(--size-selector) * 16)', 'var(--text-lg)'],
|
|
3666
|
+
};
|
|
3667
|
+
|
|
3668
|
+
export const avatarGroup: RecipeInput = {
|
|
3669
|
+
component: 'avatar-group',
|
|
3670
|
+
tokens: {
|
|
3671
|
+
'--avatar-group-size': 'calc(var(--size-selector) * 10)',
|
|
3672
|
+
'--avatar-group-text': 'var(--text-sm)',
|
|
3673
|
+
'--avatar-group-ring': 'var(--color-primary)',
|
|
3674
|
+
},
|
|
3675
|
+
parts: {
|
|
3676
|
+
root: {
|
|
3677
|
+
base: {
|
|
3678
|
+
display: 'inline-flex',
|
|
3679
|
+
alignItems: 'center',
|
|
3680
|
+
verticalAlign: 'middle',
|
|
3681
|
+
isolation: 'isolate',
|
|
3682
|
+
},
|
|
3683
|
+
},
|
|
3684
|
+
overflow: {
|
|
3685
|
+
base: {
|
|
3686
|
+
// Positioned like the avatars, or it would paint under the
|
|
3687
|
+
// face it overlaps.
|
|
3688
|
+
position: 'relative',
|
|
3689
|
+
display: 'inline-grid',
|
|
3690
|
+
placeItems: 'center',
|
|
3691
|
+
boxSizing: 'border-box',
|
|
3692
|
+
minWidth: 'var(--avatar-group-size)',
|
|
3693
|
+
height: 'var(--avatar-group-size)',
|
|
3694
|
+
paddingInline: 'var(--space-2xs)',
|
|
3695
|
+
marginInlineStart: 'calc(var(--avatar-group-size) * -0.25)',
|
|
3696
|
+
borderRadius: '9999px',
|
|
3697
|
+
boxShadow: '0 0 0 2px var(--color-base-100), 0 0 0 4px var(--avatar-group-ring)',
|
|
3698
|
+
background: 'var(--color-neutral)',
|
|
3699
|
+
color: 'var(--color-neutral-content)',
|
|
3700
|
+
fontSize: 'var(--avatar-group-text)',
|
|
3701
|
+
fontWeight: 'var(--weight-semibold)',
|
|
3702
|
+
fontVariantNumeric: 'tabular-nums',
|
|
3703
|
+
whiteSpace: 'nowrap',
|
|
3704
|
+
userSelect: 'none',
|
|
3705
|
+
},
|
|
3706
|
+
},
|
|
3707
|
+
},
|
|
3708
|
+
composes: {
|
|
3709
|
+
avatar: {
|
|
3710
|
+
parts: {
|
|
3711
|
+
root: {
|
|
3712
|
+
selectors: {
|
|
3713
|
+
'&:not(:first-child)': { marginInlineStart: 'calc(var(--avatar-group-size) * -0.25)' },
|
|
3714
|
+
},
|
|
3715
|
+
},
|
|
3716
|
+
},
|
|
3717
|
+
},
|
|
3718
|
+
},
|
|
3719
|
+
compoundVariants: [
|
|
3720
|
+
...Object.keys(avatarGroupSteps).map((size) => ({
|
|
3721
|
+
match: { size },
|
|
3722
|
+
parts: {},
|
|
3723
|
+
composes: { avatar: { axes: { size } } },
|
|
3724
|
+
})),
|
|
3725
|
+
...ROLES.map((color) => ({
|
|
3726
|
+
match: { color },
|
|
3727
|
+
parts: {},
|
|
3728
|
+
composes: { avatar: { axes: { color } } },
|
|
3729
|
+
})),
|
|
3730
|
+
],
|
|
3731
|
+
variants: {
|
|
3732
|
+
color: Object.fromEntries(ROLES.map((c) => [c, { root: { base: {
|
|
3733
|
+
'--avatar-group-ring': `var(--color-${c})`,
|
|
3734
|
+
} } }])),
|
|
3735
|
+
size: {
|
|
3736
|
+
...Object.fromEntries(Object.entries(avatarGroupSteps).map(([size, [box, text]]) => [size, { root: { base: {
|
|
3737
|
+
'--avatar-group-size': box, '--avatar-group-text': text,
|
|
3738
|
+
} } }])),
|
|
3739
|
+
// `md` is the un-attributed render — the defaults in `tokens:`.
|
|
3740
|
+
md: {},
|
|
3741
|
+
},
|
|
3742
|
+
},
|
|
3743
|
+
};
|
|
3744
|
+
|
|
3602
3745
|
/**
|
|
3603
3746
|
* A toast whose indicator is rendered (#292): the grid grows a leading column
|
|
3604
3747
|
* for the mark, and the text, action and close step one column along.
|
|
@@ -5527,6 +5670,25 @@ export const divider: RecipeInput = {
|
|
|
5527
5670
|
xl: { root: { base: { '--divider-thickness': 'calc(var(--border) * 3)' } } },
|
|
5528
5671
|
},
|
|
5529
5672
|
},
|
|
5673
|
+
targets: {
|
|
5674
|
+
lynx: {
|
|
5675
|
+
parts: {
|
|
5676
|
+
// Lynx drops the ::before/::after segments the rule is drawn
|
|
5677
|
+
// with above, which left the lynx divider with no line and,
|
|
5678
|
+
// since only those rules read `--divider-thickness`, no size
|
|
5679
|
+
// ramp either (#375). There the root itself is the line, as
|
|
5680
|
+
// it was before the segments (#356): filled with the ink and
|
|
5681
|
+
// one thickness across.
|
|
5682
|
+
root: {
|
|
5683
|
+
base: { background: 'var(--divider-ink)' },
|
|
5684
|
+
selectors: {
|
|
5685
|
+
'&[data-orientation="horizontal"]': { blockSize: 'var(--divider-thickness)' },
|
|
5686
|
+
'&[data-orientation="vertical"]': { inlineSize: 'var(--divider-thickness)' },
|
|
5687
|
+
},
|
|
5688
|
+
},
|
|
5689
|
+
},
|
|
5690
|
+
},
|
|
5691
|
+
},
|
|
5530
5692
|
};
|
|
5531
5693
|
|
|
5532
5694
|
// ── Loading (#314) ────────────────────────────────────────────────────────
|
|
@@ -7224,9 +7386,11 @@ export const steps: RecipeInput = {
|
|
|
7224
7386
|
/**
|
|
7225
7387
|
* The modal sheet's slide (#83): in from its edge, back out to it.
|
|
7226
7388
|
*
|
|
7227
|
-
* `translate` is physical, so the travel is a custom property
|
|
7228
|
-
*
|
|
7229
|
-
* and rightward in RTL (the `rtl` hedge, as
|
|
7389
|
+
* `translate` is physical, so the travel is a custom property — the whole
|
|
7390
|
+
* `x y` pair — that flips with the placement AND the direction: off the
|
|
7391
|
+
* reading start is leftward in LTR and rightward in RTL (the `rtl` hedge, as
|
|
7392
|
+
* everywhere here), while a `top` / `bottom` sheet travels on Y and mirrors
|
|
7393
|
+
* in neither (#291). Keyed on
|
|
7230
7394
|
* `data-l-dock="sheet"`, the regime, which holds through the exit where
|
|
7231
7395
|
* `:modal` does not, so the slide-out leaves from the sheet's own box.
|
|
7232
7396
|
* Opacity stays at 1: the travel is the transition. Each direction rides the
|
|
@@ -7240,16 +7404,19 @@ const sheetSlide = (enter: string, exit: string): PartStyles => {
|
|
|
7240
7404
|
return `translate ${tempo}, display ${duration} allow-discrete, overlay ${duration} allow-discrete`;
|
|
7241
7405
|
};
|
|
7242
7406
|
return {
|
|
7243
|
-
base: { '--drawer-travel': '-100%' },
|
|
7407
|
+
base: { '--drawer-travel': '-100% 0' },
|
|
7244
7408
|
selectors: {
|
|
7245
|
-
'&[data-placement="end"]': { '--drawer-travel': '100%' },
|
|
7246
|
-
[`&[data-placement="start"]${rtl}`]: { '--drawer-travel': '100%' },
|
|
7247
|
-
[`&[data-placement="end"]${rtl}`]: { '--drawer-travel': '-100%' },
|
|
7248
|
-
|
|
7409
|
+
'&[data-placement="end"]': { '--drawer-travel': '100% 0' },
|
|
7410
|
+
[`&[data-placement="start"]${rtl}`]: { '--drawer-travel': '100% 0' },
|
|
7411
|
+
[`&[data-placement="end"]${rtl}`]: { '--drawer-travel': '-100% 0' },
|
|
7412
|
+
// The block edges travel on Y, and no direction mirrors them (#291).
|
|
7413
|
+
'&[data-placement="top"]': { '--drawer-travel': '0 -100%' },
|
|
7414
|
+
'&[data-placement="bottom"]': { '--drawer-travel': '0 100%' },
|
|
7415
|
+
[sheet]: { opacity: '1', translate: 'var(--drawer-travel)', transition: travel(exit) },
|
|
7249
7416
|
[open]: { translate: 'none', transition: travel(enter) },
|
|
7250
7417
|
},
|
|
7251
7418
|
at: {
|
|
7252
|
-
'starting-style': { selectors: { [open]: { opacity: '1', translate: 'var(--drawer-travel)
|
|
7419
|
+
'starting-style': { selectors: { [open]: { opacity: '1', translate: 'var(--drawer-travel)' } } },
|
|
7253
7420
|
'reduced-motion': { selectors: { [sheet]: { transition: 'none' }, [open]: { transition: 'none' } } },
|
|
7254
7421
|
},
|
|
7255
7422
|
};
|
|
@@ -7319,6 +7486,38 @@ export const drawer: RecipeInput = {
|
|
|
7319
7486
|
},
|
|
7320
7487
|
'&[data-placement="start"][data-l-dock="sheet"]': { insetInlineStart: '0', insetInlineEnd: 'auto' },
|
|
7321
7488
|
'&[data-placement="end"][data-l-dock="sheet"]': { insetInlineStart: 'auto', insetInlineEnd: '0' },
|
|
7489
|
+
/**
|
|
7490
|
+
* The block edges (#291): a sheet across the viewport's width,
|
|
7491
|
+
* pinned with `inset-block-*` — nothing here mirrors in RTL. Its
|
|
7492
|
+
* height is this recipe's: content-sized up to most of the
|
|
7493
|
+
* viewport, so the scrim stays in reach. Full width by default —
|
|
7494
|
+
* `measure` still caps the INLINE size (centred by the auto
|
|
7495
|
+
* margins), which the `:where()` keeps below the layout step
|
|
7496
|
+
* table's specificity whatever order the files load in.
|
|
7497
|
+
*/
|
|
7498
|
+
'&:where([data-placement="top"], [data-placement="bottom"])': { '--l-measure': 'none' },
|
|
7499
|
+
'&[data-placement="top"][data-l-dock="sheet"]': {
|
|
7500
|
+
insetBlockStart: '0',
|
|
7501
|
+
insetBlockEnd: 'auto',
|
|
7502
|
+
insetInlineStart: '0',
|
|
7503
|
+
insetInlineEnd: '0',
|
|
7504
|
+
marginInline: 'auto',
|
|
7505
|
+
blockSize: 'auto',
|
|
7506
|
+
maxBlockSize: '85dvh',
|
|
7507
|
+
borderEndStartRadius: 'var(--radius-box)',
|
|
7508
|
+
borderEndEndRadius: 'var(--radius-box)',
|
|
7509
|
+
},
|
|
7510
|
+
'&[data-placement="bottom"][data-l-dock="sheet"]': {
|
|
7511
|
+
insetBlockStart: 'auto',
|
|
7512
|
+
insetBlockEnd: '0',
|
|
7513
|
+
insetInlineStart: '0',
|
|
7514
|
+
insetInlineEnd: '0',
|
|
7515
|
+
marginInline: 'auto',
|
|
7516
|
+
blockSize: 'auto',
|
|
7517
|
+
maxBlockSize: '85dvh',
|
|
7518
|
+
borderStartStartRadius: 'var(--radius-box)',
|
|
7519
|
+
borderStartEndRadius: 'var(--radius-box)',
|
|
7520
|
+
},
|
|
7322
7521
|
},
|
|
7323
7522
|
}),
|
|
7324
7523
|
backdrop: {
|
|
@@ -8151,7 +8350,7 @@ export const diff: RecipeInput = {
|
|
|
8151
8350
|
|
|
8152
8351
|
export const recipes: RecipeInput[] = [
|
|
8153
8352
|
tabs, collapsible, switchRecipe, dialog, popover, tooltip, hoverCard, menu, menubar,
|
|
8154
|
-
field, fieldset, checkbox, checkboxGroup, radioGroup, progress, slider, accordion, select, button, avatar, toast, combobox,
|
|
8353
|
+
field, fieldset, checkbox, checkboxGroup, radioGroup, progress, slider, accordion, select, button, avatar, avatarGroup, toast, combobox,
|
|
8155
8354
|
toggle, toggleGroup, numberInput, ratingGroup, treeView, input, textarea,
|
|
8156
8355
|
card, alert, emptyState, badge, divider, skeleton, spinner,
|
|
8157
8356
|
kbd, status, indicator, stats, timeline, chat, chatLog, radialProgress, join,
|