@sigx/zero-daisyui 0.10.0 → 0.11.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/dist/report.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "reportVersion": 2,
4
4
  "name": "daisyui",
5
5
  "score": {
6
- "total": 82.8,
6
+ "total": 82.7,
7
7
  "grade": "B",
8
8
  "criteria": {
9
9
  "components": {
@@ -24,14 +24,14 @@
24
24
  }
25
25
  },
26
26
  "states": {
27
- "score": 76,
27
+ "score": 75.7,
28
28
  "weight": 20,
29
29
  "detail": {
30
- "covered": 443,
30
+ "covered": 445,
31
31
  "coveredIndirectly": 0,
32
32
  "skipped": 15,
33
- "uncovered": 135,
34
- "total": 593
33
+ "uncovered": 138,
34
+ "total": 598
35
35
  }
36
36
  },
37
37
  "contrast": {
@@ -2831,7 +2831,9 @@
2831
2831
  "covered": [],
2832
2832
  "coveredIndirectly": [],
2833
2833
  "skipped": [],
2834
- "uncovered": []
2834
+ "uncovered": [
2835
+ "swiping"
2836
+ ]
2835
2837
  }
2836
2838
  },
2837
2839
  "backdrop": {
@@ -5711,6 +5713,7 @@
5711
5713
  "coveredIndirectly": [],
5712
5714
  "skipped": [],
5713
5715
  "uncovered": [
5716
+ "clearable",
5714
5717
  "press-animating",
5715
5718
  "pressed"
5716
5719
  ]
@@ -5730,7 +5733,9 @@
5730
5733
  ],
5731
5734
  "coveredIndirectly": [],
5732
5735
  "skipped": [],
5733
- "uncovered": []
5736
+ "uncovered": [
5737
+ "clearable"
5738
+ ]
5734
5739
  }
5735
5740
  },
5736
5741
  "indicator": {
@@ -5745,7 +5750,9 @@
5745
5750
  "uncovered": []
5746
5751
  },
5747
5752
  "flags": {
5748
- "covered": [],
5753
+ "covered": [
5754
+ "clearable"
5755
+ ],
5749
5756
  "coveredIndirectly": [],
5750
5757
  "skipped": [],
5751
5758
  "uncovered": []
@@ -7718,7 +7725,9 @@
7718
7725
  "uncovered": []
7719
7726
  },
7720
7727
  "flags": {
7721
- "covered": [],
7728
+ "covered": [
7729
+ "swiping"
7730
+ ],
7722
7731
  "coveredIndirectly": [],
7723
7732
  "skipped": [],
7724
7733
  "uncovered": []
@@ -9829,8 +9838,8 @@
9829
9838
  "contrast": [
9830
9839
  {
9831
9840
  "name": "light",
9832
- "cells": 3311,
9833
- "measured": 2901,
9841
+ "cells": 3318,
9842
+ "measured": 2908,
9834
9843
  "failing": 0,
9835
9844
  "warnings": 324,
9836
9845
  "disabledFailing": 0,
@@ -9905,8 +9914,8 @@
9905
9914
  },
9906
9915
  {
9907
9916
  "name": "dark",
9908
- "cells": 3311,
9909
- "measured": 2901,
9917
+ "cells": 3318,
9918
+ "measured": 2908,
9910
9919
  "failing": 0,
9911
9920
  "warnings": 168,
9912
9921
  "disabledFailing": 0,
@@ -9981,10 +9990,10 @@
9981
9990
  },
9982
9991
  {
9983
9992
  "name": "dim",
9984
- "cells": 3311,
9985
- "measured": 2901,
9993
+ "cells": 3318,
9994
+ "measured": 2908,
9986
9995
  "failing": 0,
9987
- "warnings": 269,
9996
+ "warnings": 272,
9988
9997
  "disabledFailing": 0,
9989
9998
  "unrendered": 7,
9990
9999
  "unpainted": 5,
@@ -10057,10 +10066,10 @@
10057
10066
  },
10058
10067
  {
10059
10068
  "name": "nord",
10060
- "cells": 3311,
10061
- "measured": 2901,
10069
+ "cells": 3318,
10070
+ "measured": 2908,
10062
10071
  "failing": 0,
10063
- "warnings": 1231,
10072
+ "warnings": 1234,
10064
10073
  "disabledFailing": 0,
10065
10074
  "unrendered": 7,
10066
10075
  "unpainted": 5,
@@ -10133,10 +10142,10 @@
10133
10142
  },
10134
10143
  {
10135
10144
  "name": "sunset",
10136
- "cells": 3311,
10137
- "measured": 2901,
10145
+ "cells": 3318,
10146
+ "measured": 2908,
10138
10147
  "failing": 0,
10139
- "warnings": 268,
10148
+ "warnings": 271,
10140
10149
  "disabledFailing": 0,
10141
10150
  "unrendered": 7,
10142
10151
  "unpainted": 5,
@@ -10479,7 +10488,7 @@
10479
10488
  },
10480
10489
  {
10481
10490
  "where": "lynx recipe for \"select\"",
10482
- "what": "rem lengths (14)",
10491
+ "what": "rem lengths (15)",
10483
10492
  "detail": "rewritten to px at 16px/rem — lynx resolves rem against its 14px default page font size (measured, signalxjs/lynx#1183), which would draw every rem-based size 12.5% small",
10484
10493
  "scope": "select"
10485
10494
  },
@@ -11692,8 +11701,8 @@
11692
11701
  },
11693
11702
  {
11694
11703
  "where": "lynx recipe for \"select\".\"indicator\"",
11695
- "what": "selectors[\"[data-scope=\"select\"][data-part=\"root\"]:has(> [data-scope=\"select\"][data-part=\"clear-trigger\"]) &\"]",
11696
- "detail": "not expressible in the class grammar — dropped; supply a lynx replacement in the recipe target section",
11704
+ "what": "marginInlineStart: calc(var(--space-2xl) + var(--space-sm))",
11705
+ "detail": "margin-inline-start resolves on iOS but not on Android (measured, signalxjs/lynx#1084) — cross-platform-asymmetric, treated as unsupported; dropped, restate the geometry with a physical spelling (top/right/bottom/left, margin-*/padding-*) in the recipe's lynx target section",
11697
11706
  "scope": "select"
11698
11707
  },
11699
11708
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sigx/zero-daisyui",
3
- "version": "0.10.0",
3
+ "version": "0.11.0",
4
4
  "description": "DaisyUI-flavored design system for SignalX Zero — daisy's token values and component look as a pure tokens+recipes skin over @sigx/zero primitives. No Tailwind, no daisyUI plugin required.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -62,12 +62,12 @@
62
62
  "url": "https://github.com/signalxjs/zero/issues"
63
63
  },
64
64
  "peerDependencies": {
65
- "@sigx/zero": "^0.10.0"
65
+ "@sigx/zero": "^0.11.0"
66
66
  },
67
67
  "devDependencies": {
68
68
  "typescript": "^7.0.2",
69
- "@sigx/zero": "^0.10.0",
70
- "@sigx/zero-kit": "^0.10.0"
69
+ "@sigx/zero": "^0.11.0",
70
+ "@sigx/zero-kit": "^0.11.0"
71
71
  },
72
72
  "publishConfig": {
73
73
  "access": "public"
package/src/recipes.ts CHANGED
@@ -148,6 +148,14 @@ const roleInk = (role: string): string =>
148
148
  + `${ROLE_INK_KEEP[role as keyof typeof roles] ?? 55}%, var(--color-base-content))`;
149
149
 
150
150
  // daisy "tabs-box" flavor: a rounded container, lifted active tab.
151
+ /**
152
+ * The swipe-to-dismiss offset (#293): `createSwipe` publishes the drag as
153
+ * `--swipe-x` / `--swipe-y` on a toast root or a drawer sheet, and this is
154
+ * the one place it is read — composed first into the part's `transform`, so
155
+ * an enter/exit offset or a slide rides on top of it. Unset, it is nothing.
156
+ */
157
+ const SWIPE = 'translate(var(--swipe-x, 0px), var(--swipe-y, 0px))';
158
+
151
159
  /**
152
160
  * Enter/exit presence for a top-layer popup.
153
161
  *
@@ -2933,12 +2941,6 @@ const fieldControl: NonNullable<PartStyles['base']> = {
2933
2941
  boxShadow: 'var(--shadow-xs)',
2934
2942
  };
2935
2943
 
2936
- /**
2937
- * A select whose clear-trigger is rendered (#280) — anchored on the root, so
2938
- * a part inside the trigger can make room for the button laid over it.
2939
- */
2940
- const SELECT_CLEARABLE = '[data-scope="select"][data-part="root"]:has(> [data-scope="select"][data-part="clear-trigger"]) &';
2941
-
2942
2944
  /**
2943
2945
  * The select trigger's lynx steps — `[inline padding in --size-field units,
2944
2946
  * font-size step]` — as the size variants set them (`lynxBtnPad` and the
@@ -3029,9 +3031,13 @@ export const select: RecipeInput = {
3029
3031
  },
3030
3032
  indicator: {
3031
3033
  base: { opacity: '0.6', transition: 'transform var(--duration-normal) var(--ease-standard)' },
3032
- states: { open: { transform: 'rotate(180deg)' }, closed: {} },
3033
- // Room for the clear-trigger laid over the field (#280).
3034
- selectors: { [SELECT_CLEARABLE]: { marginInlineStart: 'calc(var(--space-2xl) + var(--space-sm))' } },
3034
+ states: {
3035
+ open: { transform: 'rotate(180deg)' },
3036
+ closed: {},
3037
+ // Room for the clear-trigger laid over the field (#280) — the
3038
+ // `clearable` flag the runtime stamps while it renders (#387).
3039
+ clearable: { marginInlineStart: 'calc(var(--space-2xl) + var(--space-sm))' },
3040
+ },
3035
3041
  },
3036
3042
  // Clears the selection (#280): daisy's ghost-btn over the field's
3037
3043
  // inline end, just before the chevron — muted like it, the base-200
@@ -3189,7 +3195,25 @@ export const select: RecipeInput = {
3189
3195
  // focus ring was a tall pill. The ring is inset, so it hugs
3190
3196
  // the chip and can never reach the chevron, and no gap shadow
3191
3197
  // paints past the chip's rounded corners.
3192
- indicator: { base: { width: '1em', textAlign: 'right' } },
3198
+ indicator: {
3199
+ base: { width: '1em', textAlign: 'right' },
3200
+ // The web's room for the chip (`margin-inline-start`) is a
3201
+ // logical spelling Android never resolves, and it is
3202
+ // sized off the web's own offset. Here the chip is a
3203
+ // 1.5rem square one `--space-xs` short of the chevron
3204
+ // at every size, so the room is exactly that — and the
3205
+ // trigger's `gap` stays between the value and the chip.
3206
+ // Before the `clearable` flag the web reached this with
3207
+ // `:has()`, which lynx cannot express: at lg/xl the value
3208
+ // ran under the chip and its focus ring
3209
+ // (signalxjs/lynx#1191).
3210
+ states: { clearable: { marginLeft: 'calc(1.5rem + var(--space-xs))' } },
3211
+ },
3212
+ // The value gives way to the chip instead of running under
3213
+ // it: one line, clipped with an ellipsis — the web's
3214
+ // `nowrap` button text, with a flex item's `min-width: auto`
3215
+ // lifted so it can shrink below its content at all.
3216
+ value: { base: { flexShrink: '1', minWidth: '0', overflow: 'hidden', whiteSpace: 'nowrap', textOverflow: 'ellipsis' } },
3193
3217
  'clear-trigger': {
3194
3218
  base: { ...lynxSelectClear('md'), width: '1.5rem', height: '1.5rem', minWidth: '1.5rem', boxSizing: 'border-box' },
3195
3219
  states: lynxFocus({ inset: true }),
@@ -3210,7 +3234,6 @@ export const select: RecipeInput = {
3210
3234
  },
3211
3235
  };
3212
3236
 
3213
-
3214
3237
  /**
3215
3238
  * daisy's BUTTON ramp — `.btn`'s fixed height per size step, in `--size-field`
3216
3239
  * units, exactly as daisyUI 5 ships it (`components/button.css`: `.btn-xs`
@@ -3829,6 +3852,8 @@ export const toast: RecipeInput = {
3829
3852
  states: {
3830
3853
  open: { opacity: '1', transform: 'none' },
3831
3854
  closed: {},
3855
+ // Styled in `targets.web` — the swipe is web-only (#293).
3856
+ swiping: {},
3832
3857
  },
3833
3858
  at: {
3834
3859
  'reduced-motion': { base: { transition: 'none' }, states: { open: { transform: 'none' } } },
@@ -3954,6 +3979,22 @@ export const toast: RecipeInput = {
3954
3979
  defaultVariants: { size: 'md' },
3955
3980
  keyframes: { 'zero-daisyui-toast-spin': 'to { transform: rotate(360deg); }' },
3956
3981
  targets: {
3982
+ // The swipe (#293) — web only, since the runtime's `--swipe-*` offset
3983
+ // is: composed ahead of the enter/exit offset, and no pan or pinch
3984
+ // starts on a toast, so a touch drag is the swipe's.
3985
+ web: {
3986
+ parts: {
3987
+ root: {
3988
+ base: { transform: `${SWIPE} translateY(var(--toast-from))`, touchAction: 'none' },
3989
+ states: { open: { transform: SWIPE } },
3990
+ selectors: {
3991
+ // Mid-swipe the toast tracks the pointer, not a transition.
3992
+ '&[data-swiping]': { transition: 'none', userSelect: 'none' },
3993
+ },
3994
+ at: { 'reduced-motion': { states: { open: { transform: SWIPE } } } },
3995
+ },
3996
+ },
3997
+ },
3957
3998
  lynx: {
3958
3999
  parts: {
3959
4000
  // The viewport is a full-width strip on lynx (the runtime pins
@@ -7401,7 +7442,8 @@ const sheetSlide = (enter: string, exit: string): PartStyles => {
7401
7442
  const open = `${sheet}[data-state="open"]`;
7402
7443
  const travel = (tempo: string): string => {
7403
7444
  const duration = tempo.split(' ')[0];
7404
- return `translate ${tempo}, display ${duration} allow-discrete, overlay ${duration} allow-discrete`;
7445
+ // `transform` rides along for the swipe's spring back (#293).
7446
+ return `translate ${tempo}, transform ${tempo}, display ${duration} allow-discrete, overlay ${duration} allow-discrete`;
7405
7447
  };
7406
7448
  return {
7407
7449
  base: { '--drawer-travel': '-100% 0' },
@@ -7539,8 +7581,27 @@ export const drawer: RecipeInput = {
7539
7581
  // Trigger-carried axes — see `btnColors` for why the panel is out of
7540
7582
  // reach and the trigger is the whole story here.
7541
7583
  variants: { color: btnColors(), size: btnSizes },
7542
- // The btn paddings, restated physically — see `lynxBtnPad` (#1084).
7543
7584
  targets: {
7585
+ // Swipe to dismiss (#293) — web only, since the runtime's `--swipe-*`
7586
+ // offset is: the sheet wears the drag offset (`SWIPE`) in every
7587
+ // state — so a swiped sheet leaves from where it was let go — at a
7588
+ // weight above the presence's own open `transform`. Mid-swipe no
7589
+ // transition runs. A touch pan across the dismiss axis stays the
7590
+ // page's; along it is the gesture's, so content taller than a
7591
+ // block-edge sheet scrolls in a box of its own inside the panel.
7592
+ web: {
7593
+ parts: {
7594
+ panel: {
7595
+ selectors: {
7596
+ '&[data-l-dock="sheet"][data-state]': { transform: SWIPE },
7597
+ '&[data-l-dock="sheet"][data-state="open"][data-swiping]': { transition: 'none', userSelect: 'none' },
7598
+ '&[data-l-dock="sheet"]:where([data-placement="start"], [data-placement="end"])': { touchAction: 'pan-y' },
7599
+ '&[data-l-dock="sheet"]:where([data-placement="top"], [data-placement="bottom"])': { touchAction: 'pan-x' },
7600
+ },
7601
+ },
7602
+ },
7603
+ },
7604
+ // The btn paddings, restated physically — see `lynxBtnPad` (#1084).
7544
7605
  lynx: {
7545
7606
  parts: {
7546
7607
  trigger: { base: lynxBtnPad(4) },