@nadicodeai/ui 12.1.27 → 12.1.29

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.
@@ -0,0 +1 @@
1
+ clean
@@ -20,7 +20,7 @@ function CardHeader({ className, ...props }) {
20
20
  // `minmax(0,1fr)`, not `1fr`, because a `1fr` track never shrinks below
21
21
  // its content and a long title or an unbreakable figure would push the
22
22
  // action past the card's edge, where the card's clipping cuts it.
23
- "group/card-header @container/card-header grid auto-rows-min items-start gap-1 rounded-t-md px-(--card-spacing) has-data-[slot=card-action]:grid-cols-[minmax(0,1fr)_auto] has-data-[slot=card-description]:grid-rows-[auto_auto] [.border-b]:pb-(--card-spacing)", className), ...props }));
23
+ "group/card-header @container/card-header grid auto-rows-min items-start gap-1 rounded-t-md px-(--card-spacing) has-data-[slot=card-action]:grid-cols-[minmax(0,1fr)_auto] has-data-[slot=card-description]:grid-rows-[auto_auto] *:data-[slot=card-description]:col-start-1 *:data-[slot=card-title]:col-start-1 [.border-b]:pb-(--card-spacing)", className), ...props }));
24
24
  }
25
25
  function CardTitle({ className, focusTarget = false, ...props }) {
26
26
  return (_jsx("div", { "data-slot": "card-title", "data-focus-target": focusTarget || undefined, className: cn("text-base font-medium group-data-[size=sm]/card:text-sm", focusTarget && "rounded-sm", className), ...props }));
@@ -9,6 +9,11 @@ declare function DrawerClose({ ...props }: DrawerPrimitive.Close.Props): React.J
9
9
  declare function DrawerOverlay({ className, ...props }: DrawerPrimitive.Backdrop.Props): React.JSX.Element;
10
10
  declare function DrawerSwipeHandle({ className, ...props }: React.ComponentProps<"div">): React.JSX.Element;
11
11
  declare function DrawerContent({ className, children, ...props }: DrawerPrimitive.Popup.Props): React.JSX.Element;
12
+ /**
13
+ * The header and the footer stay in place while the body scrolls between them,
14
+ * so each draws the one hairline that separates it from the body; a caller
15
+ * adds no edge of its own.
16
+ */
12
17
  declare function DrawerHeader({ className, ...props }: React.ComponentProps<"div">): React.JSX.Element;
13
18
  /**
14
19
  * The part of a drawer that scrolls, between its header and footer, which stay
@@ -1 +1 @@
1
- {"version":3,"file":"drawer.d.ts","sourceRoot":"","sources":["../../src/components/drawer.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,MAAM,IAAI,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAuBlE,iBAAS,MAAM,CAAC,EACd,KAAY,EACZ,eAAuB,EACvB,UAAU,EACV,cAAuB,EACvB,GAAG,KAAK,EACT,EAAE,eAAe,CAAC,IAAI,CAAC,KAAK,GAAG;IAC9B,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B,qBAkBA;AAED,iBAAS,aAAa,CAAC,EAAE,GAAG,KAAK,EAAE,EAAE,eAAe,CAAC,OAAO,CAAC,KAAK,qBAEjE;AAED,iBAAS,YAAY,CAAC,EAAE,GAAG,KAAK,EAAE,EAAE,eAAe,CAAC,MAAM,CAAC,KAAK,qBAE/D;AAED,iBAAS,WAAW,CAAC,EAAE,GAAG,KAAK,EAAE,EAAE,eAAe,CAAC,KAAK,CAAC,KAAK,qBAE7D;AAED,iBAAS,aAAa,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,eAAe,CAAC,QAAQ,CAAC,KAAK,qBAW7E;AAED,iBAAS,iBAAiB,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,qBAY9E;AAED,iBAAS,aAAa,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,KAAK,EAAE,EAAE,eAAe,CAAC,KAAK,CAAC,KAAK,qBA0DpF;AAED,iBAAS,YAAY,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,qBAWzE;AAED;;;GAGG;AACH,iBAAS,UAAU,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,qBAWvE;AAED,iBAAS,YAAY,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,qBAQzE;AAED,iBAAS,WAAW,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,eAAe,CAAC,KAAK,CAAC,KAAK,qBAQxE;AAED,iBAAS,iBAAiB,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,eAAe,CAAC,WAAW,CAAC,KAAK,qBAQpF;AAED,OAAO,EACL,MAAM,EACN,YAAY,EACZ,aAAa,EACb,iBAAiB,EACjB,aAAa,EACb,WAAW,EACX,aAAa,EACb,YAAY,EACZ,UAAU,EACV,YAAY,EACZ,WAAW,EACX,iBAAiB,GAClB,CAAC"}
1
+ {"version":3,"file":"drawer.d.ts","sourceRoot":"","sources":["../../src/components/drawer.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,MAAM,IAAI,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAuBlE,iBAAS,MAAM,CAAC,EACd,KAAY,EACZ,eAAuB,EACvB,UAAU,EACV,cAAuB,EACvB,GAAG,KAAK,EACT,EAAE,eAAe,CAAC,IAAI,CAAC,KAAK,GAAG;IAC9B,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B,qBAkBA;AAED,iBAAS,aAAa,CAAC,EAAE,GAAG,KAAK,EAAE,EAAE,eAAe,CAAC,OAAO,CAAC,KAAK,qBAEjE;AAED,iBAAS,YAAY,CAAC,EAAE,GAAG,KAAK,EAAE,EAAE,eAAe,CAAC,MAAM,CAAC,KAAK,qBAE/D;AAED,iBAAS,WAAW,CAAC,EAAE,GAAG,KAAK,EAAE,EAAE,eAAe,CAAC,KAAK,CAAC,KAAK,qBAE7D;AAED,iBAAS,aAAa,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,eAAe,CAAC,QAAQ,CAAC,KAAK,qBAW7E;AAED,iBAAS,iBAAiB,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,qBAY9E;AAED,iBAAS,aAAa,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,KAAK,EAAE,EAAE,eAAe,CAAC,KAAK,CAAC,KAAK,qBA0DpF;AAED;;;;GAIG;AACH,iBAAS,YAAY,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,qBAWzE;AAED;;;GAGG;AACH,iBAAS,UAAU,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,qBAWvE;AAED,iBAAS,YAAY,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,qBAWzE;AAED,iBAAS,WAAW,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,eAAe,CAAC,KAAK,CAAC,KAAK,qBAQxE;AAED,iBAAS,iBAAiB,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,eAAe,CAAC,WAAW,CAAC,KAAK,qBAQpF;AAED,OAAO,EACL,MAAM,EACN,YAAY,EACZ,aAAa,EACb,iBAAiB,EACjB,aAAa,EACb,WAAW,EACX,aAAa,EACb,YAAY,EACZ,UAAU,EACV,YAAY,EACZ,WAAW,EACX,iBAAiB,GAClB,CAAC"}
@@ -46,7 +46,7 @@ function DrawerContent({ className, children, ...props }) {
46
46
  // Stack.
47
47
  "[--bleed:3rem] [--peek:1rem] [--stack-height:var(--drawer-frontmost-height,var(--drawer-height,0px))] [--stack-peek-offset:max(0px,calc((var(--nested-drawers)-var(--stack-progress))*var(--peek)))] [--stack-progress:clamp(0,var(--drawer-swipe-progress),1)] [--stack-scale-base:max(0,calc(1-(var(--nested-drawers)*var(--stack-step))))] [--stack-scale:clamp(0,calc(var(--stack-scale-base)+(var(--stack-step)*var(--stack-progress))),1)] [--stack-shrink:calc(1-var(--stack-scale))] [--stack-step:0.05]",
48
48
  // Transitions.
49
- "data-ending-style:transform-(--closed-transform) data-ending-style:opacity-[0.9999] data-ending-style:duration-[calc(var(--drawer-swipe-strength)*var(--nc-duration-drawer-swipe))] data-nested-drawer-swiping:duration-0 data-ending-style:data-nested-drawer-swiping:duration-[calc(var(--drawer-swipe-strength)*var(--nc-duration-drawer-swipe))] data-starting-style:transform-(--closed-transform) data-swiping:duration-0 data-ending-style:data-swiping:duration-[calc(var(--drawer-swipe-strength)*var(--nc-duration-drawer-swipe))] motion-reduce:data-ending-style:transform-none motion-reduce:data-starting-style:transform-none",
49
+ "data-ending-style:transform-(--closed-transform) data-ending-style:opacity-[0.9999] data-ending-style:duration-[calc(var(--drawer-swipe-strength)*var(--nc-duration-drawer-swipe))] data-nested-drawer-swiping:duration-0 data-ending-style:data-nested-drawer-swiping:duration-[calc(var(--drawer-swipe-strength)*var(--nc-duration-drawer-swipe))] data-starting-style:transform-(--closed-transform) data-swiping:duration-0 data-ending-style:data-swiping:duration-[calc(var(--drawer-swipe-strength)*var(--nc-duration-drawer-swipe))] motion-reduce:data-ending-style:transform-none motion-reduce:data-starting-style:transform-none motion-reduce:data-ending-style:opacity-0 motion-reduce:data-starting-style:opacity-0",
50
50
  // Axis: y.
51
51
  "data-[swipe-axis=y]:inset-x-0 data-[swipe-axis=y]:data-nested-drawer-open:h-(--stack-height)",
52
52
  // Axis: x.
@@ -60,8 +60,13 @@ function DrawerContent({ className, children, ...props }) {
60
60
  // Direction: right.
61
61
  "data-[swipe-direction=right]:right-0 data-[swipe-direction=right]:origin-right data-[swipe-direction=right]:[--closed-transform:translate3d(calc(100%+var(--drawer-inset,0px)+2px),0,0)] data-[swipe-direction=right]:[--translate-x:calc(var(--drawer-swipe-movement-x)-var(--stack-peek-offset)-(var(--stack-shrink)*100%))]", className), ...props, children: [showSwipeHandle && _jsx(DrawerSwipeHandle, {}), _jsx(DrawerPrimitive.Content, { "data-slot": "drawer-content", className: cn("flex min-h-0 flex-1 flex-col overflow-hidden overscroll-contain rounded-[inherit] transition-opacity duration-[var(--nc-duration-open)] ease-[var(--nc-ease-out-strong)] select-text group-data-nested-drawer-open/drawer-popup:opacity-0 group-data-nested-drawer-swiping/drawer-popup:opacity-100 group-data-swiping/drawer-popup:select-none"), children: children })] }) })] }));
62
62
  }
63
+ /**
64
+ * The header and the footer stay in place while the body scrolls between them,
65
+ * so each draws the one hairline that separates it from the body; a caller
66
+ * adds no edge of its own.
67
+ */
63
68
  function DrawerHeader({ className, ...props }) {
64
- return (_jsx("div", { "data-slot": "drawer-header", className: cn("flex shrink-0 flex-col gap-0.5 p-nadicode-lg pb-0 group-data-[swipe-axis=y]/drawer-popup:text-center md:gap-0.5 md:text-left", className), ...props }));
69
+ return (_jsx("div", { "data-slot": "drawer-header", className: cn("flex shrink-0 flex-col gap-0.5 border-b border-border p-nadicode-lg pb-nadicode-md group-data-[swipe-axis=y]/drawer-popup:text-center md:gap-0.5 md:text-left", className), ...props }));
65
70
  }
66
71
  /**
67
72
  * The part of a drawer that scrolls, between its header and footer, which stay
@@ -71,7 +76,7 @@ function DrawerBody({ className, ...props }) {
71
76
  return (_jsx("div", { "data-slot": "drawer-body", className: cn("flex min-h-0 flex-1 flex-col gap-nadicode-md overflow-y-auto p-nadicode-lg", className), ...props }));
72
77
  }
73
78
  function DrawerFooter({ className, ...props }) {
74
- return (_jsx("div", { "data-slot": "drawer-footer", className: cn("mt-auto flex shrink-0 flex-col gap-2 p-nadicode-lg pt-0", className), ...props }));
79
+ return (_jsx("div", { "data-slot": "drawer-footer", className: cn("mt-auto flex shrink-0 flex-col gap-2 border-t border-border p-nadicode-md", className), ...props }));
75
80
  }
76
81
  function DrawerTitle({ className, ...props }) {
77
82
  return (_jsx(DrawerPrimitive.Title, { "data-slot": "drawer-title", className: cn("text-base font-medium text-foreground", className), ...props }));
@@ -4,6 +4,7 @@ import { readdirSync, readFileSync } from "node:fs";
4
4
  import { menuCommandOwner } from "./rules/menu-command-owner.js";
5
5
  import { cardRowOwner } from "./rules/card-row-owner.js";
6
6
  import { confirmDestructiveAction } from "./rules/confirm-destructive-action.js";
7
+ import { drawerOwnsItsEdges } from "./rules/drawer-owns-its-edges.js";
7
8
  import { iconControlAccessibleName } from "./rules/icon-control-accessible-name.js";
8
9
  import { noAppFeatureComponent } from "./rules/no-app-feature-component.js";
9
10
  import { noElevatedEdge } from "./rules/no-elevated-edge.js";
@@ -20,6 +21,7 @@ import { noPairedSizeUtility } from "./rules/no-paired-size-utility.js";
20
21
  import { noRestingSettingsControl } from "./rules/no-resting-settings-control.js";
21
22
  import { oneControlHeight } from "./rules/one-control-height.js";
22
23
  import { overlayBodyOwnsScroll } from "./rules/overlay-body-owns-scroll.js";
24
+ import { overlayMountsClosed } from "./rules/overlay-mounts-closed.js";
23
25
  import { tableColumnWrapsByMeta } from "./rules/table-column-wraps-by-meta.js";
24
26
  import { noShadcnAppearanceOverride } from "./rules/no-shadcn-appearance-override.js";
25
27
  import { noSubjectDerivedExpectation } from "./rules/no-subject-derived-expectation.js";
@@ -88,6 +90,7 @@ function digestOf(paths) {
88
90
 
89
91
  export const strictDesignSystemRules = {
90
92
  "nadicodeai/card-row-owner": "error",
93
+ "nadicodeai/drawer-owns-its-edges": "error",
91
94
  "nadicodeai/icon-control-accessible-name": "error",
92
95
  "nadicodeai/no-invalid-token-utility": "error",
93
96
  "nadicodeai/no-native-visible-control": "error",
@@ -98,6 +101,7 @@ export const strictDesignSystemRules = {
98
101
  "nadicodeai/no-shadcn-appearance-override": "error",
99
102
  "nadicodeai/no-token-category-bypass": "error",
100
103
  "nadicodeai/overlay-body-owns-scroll": "error",
104
+ "nadicodeai/overlay-mounts-closed": "error",
101
105
  "nadicodeai/prefer-radio-for-few-static-options": "error",
102
106
  };
103
107
 
@@ -112,6 +116,7 @@ const plugin = {
112
116
  "card-row-owner": cardRowOwner,
113
117
  "menu-command-owner": menuCommandOwner,
114
118
  "confirm-destructive-action": confirmDestructiveAction,
119
+ "drawer-owns-its-edges": drawerOwnsItsEdges,
115
120
  "icon-control-accessible-name": iconControlAccessibleName,
116
121
  "no-app-feature-component": noAppFeatureComponent,
117
122
  "no-elevated-edge": noElevatedEdge,
@@ -135,6 +140,7 @@ const plugin = {
135
140
  "no-token-category-bypass": noTokenCategoryBypass,
136
141
  "one-control-height": oneControlHeight,
137
142
  "overlay-body-owns-scroll": overlayBodyOwnsScroll,
143
+ "overlay-mounts-closed": overlayMountsClosed,
138
144
  "table-column-wraps-by-meta": tableColumnWrapsByMeta,
139
145
  "server-action-discipline": serverActionDiscipline,
140
146
  "settings-section-description": settingsSectionDescription,
@@ -0,0 +1,66 @@
1
+ /*
2
+ * Standard tool checked first: `better-tailwindcss/no-restricted-classes` bans a
3
+ * class everywhere and cannot ask which element it sits on or what that element
4
+ * wraps, so the relationship is read here on the shared readers.
5
+ */
6
+ import { jsxComponentName, openingElementClassUtilities } from "./jsx-class-utility.js";
7
+
8
+ const SLOTS = new Set(["DrawerHeader", "DrawerBody", "DrawerFooter"]);
9
+
10
+ const EDGE = /^border(?:-[tby])?(?:-\d+)?$/;
11
+
12
+ function edgeUtility(node, context) {
13
+ return openingElementClassUtilities(node, context).find((utility) =>
14
+ EDGE.test(utility.split(":").at(-1).replace(/^!/, "")),
15
+ );
16
+ }
17
+
18
+ function wrappedSlot(element, context) {
19
+ for (const child of element.children) {
20
+ if (child.type !== "JSXElement") continue;
21
+ const name = jsxComponentName(child.openingElement, context);
22
+ if (name && SLOTS.has(name)) return name;
23
+ }
24
+ return undefined;
25
+ }
26
+
27
+ export const drawerOwnsItsEdges = {
28
+ meta: {
29
+ type: "problem",
30
+ docs: {
31
+ description: "Keep the edges between a drawer's header, body and footer with the drawer",
32
+ },
33
+ schema: [],
34
+ messages: {
35
+ slotEdge:
36
+ '"{{utility}}" gives <{{slot}}> a second edge. The drawer draws the hairline between its header, its body and its footer; drop the border class (rule/drawer-owns-its-edges).',
37
+ wrapperEdge:
38
+ '"{{utility}}" draws an edge around <{{slot}}>. The drawer draws the hairline between its header, its body and its footer; render the slot without this wrapper (rule/drawer-owns-its-edges).',
39
+ },
40
+ },
41
+ create(context) {
42
+ return {
43
+ JSXElement(element) {
44
+ const utility = edgeUtility(element.openingElement, context);
45
+ if (!utility) return;
46
+ const own = jsxComponentName(element.openingElement, context);
47
+ if (own && SLOTS.has(own)) {
48
+ context.report({
49
+ node: element.openingElement,
50
+ messageId: "slotEdge",
51
+ data: { utility, slot: own },
52
+ });
53
+ return;
54
+ }
55
+ const slot = wrappedSlot(element, context);
56
+ if (slot) {
57
+ context.report({
58
+ node: element.openingElement,
59
+ messageId: "wrapperEdge",
60
+ data: { utility, slot },
61
+ });
62
+ }
63
+ },
64
+ };
65
+ },
66
+ };
@@ -0,0 +1,102 @@
1
+ /*
2
+ * An overlay is mounted closed and then opened, so its entry runs.
3
+ *
4
+ * A dialog, drawer, sheet or menu fades in from its starting style when its
5
+ * `open` turns true on a mounted element. One that first mounts already open
6
+ * has no earlier frame to transition from, so it appears at full opacity, and
7
+ * one that unmounts on dismissal never plays its exit. Three spellings mount an
8
+ * overlay open: an `open` fixed to true (its parent mounts it on demand), a
9
+ * truthy `defaultOpen`, and a `key` that changes per opening, which remounts it
10
+ * in the same render that opens it. A list key inside a `.map` callback and a
11
+ * literal key are an element's identity, not an opening.
12
+ *
13
+ * Standard tool checked first: `no-restricted-syntax` can match the attribute,
14
+ * but not the renamed import or the enclosing `.map` a list key sits in, so the
15
+ * shared component-name reader resolves it here.
16
+ */
17
+ import { jsxComponentName } from "./jsx-class-utility.js";
18
+
19
+ const OVERLAY = /Dialog|Drawer|Sheet|Popover|Menu|Tooltip|HoverCard|Combobox/;
20
+ const PART =
21
+ /(Content|Trigger|Title|Description|Header|Footer|Body|Item|Group|Label|Separator|Close|Portal|Overlay|Backdrop)$/;
22
+ const LIST_CALLBACK = new Set(["map", "flatMap"]);
23
+
24
+ function attribute(node, name) {
25
+ return node.attributes.find(
26
+ (entry) =>
27
+ entry.type === "JSXAttribute" &&
28
+ entry.name.type === "JSXIdentifier" &&
29
+ entry.name.name === name,
30
+ );
31
+ }
32
+
33
+ function isTrue(entry) {
34
+ if (!entry) return false;
35
+ if (entry.value === null) return true;
36
+ return (
37
+ entry.value.type === "JSXExpressionContainer" &&
38
+ entry.value.expression.type === "Literal" &&
39
+ entry.value.expression.value === true
40
+ );
41
+ }
42
+
43
+ function isLiteralKey(entry) {
44
+ if (entry.value?.type === "Literal") return true;
45
+ const expression =
46
+ entry.value?.type === "JSXExpressionContainer" ? entry.value.expression : undefined;
47
+ return (
48
+ expression?.type === "Literal" ||
49
+ (expression?.type === "TemplateLiteral" && expression.expressions.length === 0)
50
+ );
51
+ }
52
+
53
+ function insideListCallback(node, context) {
54
+ return context.sourceCode
55
+ .getAncestors(node)
56
+ .some(
57
+ (ancestor) =>
58
+ (ancestor.type === "ArrowFunctionExpression" || ancestor.type === "FunctionExpression") &&
59
+ ancestor.parent?.type === "CallExpression" &&
60
+ ancestor.parent.arguments.includes(ancestor) &&
61
+ ancestor.parent.callee.type === "MemberExpression" &&
62
+ LIST_CALLBACK.has(ancestor.parent.callee.property.name),
63
+ );
64
+ }
65
+
66
+ export const overlayMountsClosed = {
67
+ meta: {
68
+ type: "problem",
69
+ docs: {
70
+ description:
71
+ "Disallow an overlay that mounts already open, so its entry and exit transitions run",
72
+ },
73
+ schema: [],
74
+ messages: {
75
+ openFixed:
76
+ "<{{name}}> is given `open` fixed to true, so it only exists while open and neither its fade in nor its fade out runs. Keep it mounted and drive `open` from state.",
77
+ defaultOpen:
78
+ "<{{name}}> mounts open through `defaultOpen`, so its entry never runs. Mount it closed and open it from state.",
79
+ keyPerOpening:
80
+ "<{{name}}> takes a `key` that remounts it, so an opening that changes the key mounts it already open and its fade in never runs. Keep one mounted overlay and reset its content another way, such as a key on the content inside it.",
81
+ },
82
+ },
83
+ create(context) {
84
+ return {
85
+ JSXOpeningElement(node) {
86
+ const name = jsxComponentName(node, context);
87
+ if (!name || !OVERLAY.test(name) || PART.test(name)) return;
88
+
89
+ if (isTrue(attribute(node, "open"))) {
90
+ context.report({ node, messageId: "openFixed", data: { name } });
91
+ }
92
+ if (isTrue(attribute(node, "defaultOpen"))) {
93
+ context.report({ node, messageId: "defaultOpen", data: { name } });
94
+ }
95
+ const key = attribute(node, "key");
96
+ if (key && !isLiteralKey(key) && !insideListCallback(node, context)) {
97
+ context.report({ node, messageId: "keyPerOpening", data: { name } });
98
+ }
99
+ },
100
+ };
101
+ },
102
+ };
package/dist/index.d.ts CHANGED
@@ -52,7 +52,6 @@ export * from "./components/drawer.js";
52
52
  export * from "./components/dropdown-menu.js";
53
53
  export * from "./components/empty.js";
54
54
  export * from "./components/expandable-block.js";
55
- export * from "./components/fact-cell.js";
56
55
  export * from "./components/feedback-state.js";
57
56
  export * from "./components/field.js";
58
57
  export * from "./components/file-diff.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -52,7 +52,6 @@ export * from "./components/drawer.js";
52
52
  export * from "./components/dropdown-menu.js";
53
53
  export * from "./components/empty.js";
54
54
  export * from "./components/expandable-block.js";
55
- export * from "./components/fact-cell.js";
56
55
  export * from "./components/feedback-state.js";
57
56
  export * from "./components/field.js";
58
57
  export * from "./components/file-diff.js";
@@ -1 +1 @@
1
- {"version":3,"file":"tool-fallback.d.ts","sourceRoot":"","sources":["../../../src/internal/assistant-ui/tool-fallback.tsx"],"names":[],"mappings":"AAUA,OAAO,EAOL,KAAK,4BAA4B,EAClC,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,WAAW,EAA0C,MAAM,0BAA0B,CAAC;AAQ/F,MAAM,MAAM,qBAAqB,GAAG,IAAI,CACtC,KAAK,CAAC,cAAc,CAAC,OAAO,WAAW,CAAC,EACxC,MAAM,GAAG,cAAc,CACxB,GAAG;IACF,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACvC,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,CAAC;AAydF,QAAA,MAAM,YAAY,EAAwC,4BAA4B,CAAC;AAIvF,OAAO,EAAE,YAAY,EAAE,CAAC"}
1
+ {"version":3,"file":"tool-fallback.d.ts","sourceRoot":"","sources":["../../../src/internal/assistant-ui/tool-fallback.tsx"],"names":[],"mappings":"AAUA,OAAO,EAOL,KAAK,4BAA4B,EAClC,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,WAAW,EAA0C,MAAM,0BAA0B,CAAC;AAO/F,MAAM,MAAM,qBAAqB,GAAG,IAAI,CACtC,KAAK,CAAC,cAAc,CAAC,OAAO,WAAW,CAAC,EACxC,MAAM,GAAG,cAAc,CACxB,GAAG;IACF,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACvC,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,CAAC;AAydF,QAAA,MAAM,YAAY,EAAwC,4BAA4B,CAAC;AAIvF,OAAO,EAAE,YAAY,EAAE,CAAC"}
@@ -5,13 +5,13 @@ import { AlertCircleIcon, CheckIcon, ChevronDownIcon, CircleDotIcon, XCircleIcon
5
5
  import { useScrollLock, useToolCallElapsed, } from "@assistant-ui/react";
6
6
  import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "../../components/collapsible.js";
7
7
  import { cn } from "../../lib/utils.js";
8
+ import { disclosureDuration, disclosureDurationMs } from "../../lib/motion.js";
8
9
  import { Button } from "../../components/button.js";
9
- const ANIMATION_DURATION = 200;
10
10
  const pressable = "active:scale-[0.98]";
11
11
  function ToolFallbackRoot({ className, open: controlledOpen, onOpenChange: controlledOnOpenChange, defaultOpen = false, children, ...props }) {
12
12
  const collapsibleRef = useRef(null);
13
13
  const [uncontrolledOpen, setUncontrolledOpen] = useState(defaultOpen);
14
- const lockScroll = useScrollLock(collapsibleRef, ANIMATION_DURATION);
14
+ const lockScroll = useScrollLock(collapsibleRef, disclosureDurationMs);
15
15
  const isControlled = controlledOpen !== undefined;
16
16
  const isOpen = isControlled ? controlledOpen : uncontrolledOpen;
17
17
  const handleOpenChange = useCallback((open) => {
@@ -22,7 +22,7 @@ function ToolFallbackRoot({ className, open: controlledOpen, onOpenChange: contr
22
22
  controlledOnOpenChange?.(open);
23
23
  }, [lockScroll, isControlled, controlledOnOpenChange]);
24
24
  return (_jsx(Collapsible, { ref: collapsibleRef, "data-slot": "tool-fallback-root", open: isOpen, onOpenChange: handleOpenChange, className: cn("aui-tool-fallback-root group/tool-fallback-root w-full", className), style: {
25
- "--animation-duration": `${ANIMATION_DURATION}ms`,
25
+ "--animation-duration": disclosureDuration,
26
26
  }, ...props, children: children }));
27
27
  }
28
28
  const statusIconMap = {
@@ -1 +1 @@
1
- {"version":3,"file":"tool-group.d.ts","sourceRoot":"","sources":["../../../src/internal/assistant-ui/tool-group.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAElE,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAK/F,QAAA,MAAM,iBAAiB;;8EASrB,CAAC;AAEH,MAAM,MAAM,kBAAkB,GAAG,IAAI,CACnC,KAAK,CAAC,cAAc,CAAC,OAAO,WAAW,CAAC,EACxC,MAAM,GAAG,cAAc,CACxB,GACC,YAAY,CAAC,OAAO,iBAAiB,CAAC,GAAG;IACvC,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACvC,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,CAAC;AAEJ,iBAAS,aAAa,CAAC,EACrB,SAAS,EACT,OAAO,EACP,IAAI,EAAE,cAAc,EACpB,YAAY,EAAE,sBAAsB,EACpC,WAAmB,EACnB,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,kBAAkB,+BAqCpB;AAED,iBAAS,gBAAgB,CAAC,EACxB,KAAK,EACL,MAAc,EACd,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,kBAAkB,CAAC,GAAG;IACnD,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB,+BAwCA;AAED,iBAAS,gBAAgB,CAAC,EACxB,SAAS,EACT,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,kBAAkB,CAAC,+BAyBjD;AAED,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,CAAC"}
1
+ {"version":3,"file":"tool-group.d.ts","sourceRoot":"","sources":["../../../src/internal/assistant-ui/tool-group.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAElE,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAI/F,QAAA,MAAM,iBAAiB;;8EASrB,CAAC;AAEH,MAAM,MAAM,kBAAkB,GAAG,IAAI,CACnC,KAAK,CAAC,cAAc,CAAC,OAAO,WAAW,CAAC,EACxC,MAAM,GAAG,cAAc,CACxB,GACC,YAAY,CAAC,OAAO,iBAAiB,CAAC,GAAG;IACvC,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACvC,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,CAAC;AAEJ,iBAAS,aAAa,CAAC,EACrB,SAAS,EACT,OAAO,EACP,IAAI,EAAE,cAAc,EACpB,YAAY,EAAE,sBAAsB,EACpC,WAAmB,EACnB,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,kBAAkB,+BAqCpB;AAED,iBAAS,gBAAgB,CAAC,EACxB,KAAK,EACL,MAAc,EACd,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,kBAAkB,CAAC,GAAG;IACnD,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB,+BAwCA;AAED,iBAAS,gBAAgB,CAAC,EACxB,SAAS,EACT,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,kBAAkB,CAAC,+BAyBjD;AAED,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,CAAC"}
@@ -6,7 +6,7 @@ import { cva } from "class-variance-authority";
6
6
  import { useScrollLock } from "@assistant-ui/react";
7
7
  import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "../../components/collapsible.js";
8
8
  import { cn } from "../../lib/utils.js";
9
- const ANIMATION_DURATION = 200;
9
+ import { disclosureDuration, disclosureDurationMs } from "../../lib/motion.js";
10
10
  const toolGroupVariants = cva("aui-tool-group-root group/tool-group w-full", {
11
11
  variants: {
12
12
  variant: {
@@ -20,7 +20,7 @@ const toolGroupVariants = cva("aui-tool-group-root group/tool-group w-full", {
20
20
  function ToolGroupRoot({ className, variant, open: controlledOpen, onOpenChange: controlledOnOpenChange, defaultOpen = false, children, ...props }) {
21
21
  const collapsibleRef = useRef(null);
22
22
  const [uncontrolledOpen, setUncontrolledOpen] = useState(defaultOpen);
23
- const lockScroll = useScrollLock(collapsibleRef, ANIMATION_DURATION);
23
+ const lockScroll = useScrollLock(collapsibleRef, disclosureDurationMs);
24
24
  const isControlled = controlledOpen !== undefined;
25
25
  const isOpen = isControlled ? controlledOpen : uncontrolledOpen;
26
26
  const handleOpenChange = useCallback((open) => {
@@ -31,7 +31,7 @@ function ToolGroupRoot({ className, variant, open: controlledOpen, onOpenChange:
31
31
  controlledOnOpenChange?.(open);
32
32
  }, [lockScroll, isControlled, controlledOnOpenChange]);
33
33
  return (_jsx(Collapsible, { ref: collapsibleRef, "data-slot": "tool-group-root", "data-variant": variant ?? "outline", open: isOpen, onOpenChange: handleOpenChange, className: cn(toolGroupVariants({ variant }), "group/tool-group-root", className), style: {
34
- "--animation-duration": `${ANIMATION_DURATION}ms`,
34
+ "--animation-duration": disclosureDuration,
35
35
  }, ...props, children: children }));
36
36
  }
37
37
  function ToolGroupTrigger({ count, active = false, className, ...props }) {
@@ -128,3 +128,26 @@
128
128
  @source "../components";
129
129
  @source "../internal";
130
130
  @source "../lib";
131
+
132
+ @container card-header (width < 28rem) {
133
+ [data-slot="card-action"]:not(:empty):not(
134
+ :has(
135
+ > :only-child:is(
136
+ [data-slot="badge"],
137
+ [data-slot="trend-badge"],
138
+ [data-slot="button"][aria-label],
139
+ [data-slot="dropdown-menu-trigger"][aria-label]
140
+ )
141
+ )
142
+ ) {
143
+ grid-column: 1;
144
+ grid-row: auto;
145
+ justify-self: start;
146
+ justify-content: flex-start;
147
+ margin-top: var(--spacing-nadicode-xs);
148
+
149
+ & > div {
150
+ justify-content: flex-start;
151
+ }
152
+ }
153
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nadicodeai/ui",
3
- "version": "12.1.27",
3
+ "version": "12.1.29",
4
4
  "type": "module",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -76,7 +76,7 @@
76
76
  "@assistant-ui/react": "0.15.21",
77
77
  "@assistant-ui/react-markdown": "0.14.16",
78
78
  "@base-ui/react": "^1.8.0",
79
- "@nadicodeai/design-system": "12.1.27",
79
+ "@nadicodeai/design-system": "12.1.29",
80
80
  "class-variance-authority": "^0.7.1",
81
81
  "clsx": "^2.1.1",
82
82
  "cmdk": "^1.1.1",
@@ -1,21 +0,0 @@
1
- import * as React from "react";
2
- /**
3
- * fact-cell — mono-kicker + claim content fill (replaces the retired `.nc-fact-cell`).
4
- *
5
- * A seam-free fill: it drops into a seam-owning grid (which paints the hairline gaps
6
- * between cells), so it draws NO border and is square-cornered. It carries the canvas
7
- * surface, a mono label, and a claim. `surface="ink"` inverts onto the ink role;
8
- * `size="sm"` is the compact 86px action-card rhythm.
9
- *
10
- * Server-renderable: the ink inversion + sm claim sizing are applied by the parent
11
- * to its descendants via `data-slot` descendant selectors (the retired CSS-cascade
12
- * model), so sub-components stay style-light. Token-only; no `dark:` styling.
13
- */
14
- declare function FactCell({ className, surface, size, ...props }: React.ComponentProps<"div"> & {
15
- surface?: "canvas" | "ink";
16
- size?: "default" | "sm";
17
- }): React.JSX.Element;
18
- declare function FactCellLabel({ className, ...props }: React.ComponentProps<"div">): React.JSX.Element;
19
- declare function FactCellClaim({ className, ...props }: React.ComponentProps<"div">): React.JSX.Element;
20
- export { FactCell, FactCellLabel, FactCellClaim };
21
- //# sourceMappingURL=fact-cell.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"fact-cell.d.ts","sourceRoot":"","sources":["../../src/components/fact-cell.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAI/B;;;;;;;;;;;GAWG;AAEH,iBAAS,QAAQ,CAAC,EAChB,SAAS,EACT,OAAkB,EAClB,IAAgB,EAChB,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,GAAG;IAC/B,OAAO,CAAC,EAAE,QAAQ,GAAG,KAAK,CAAC;IAC3B,IAAI,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC;CACzB,qBAsBA;AAED,iBAAS,aAAa,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,qBAQ1E;AAED,iBAAS,aAAa,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,qBAQ1E;AAED,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,aAAa,EAAE,CAAC"}
@@ -1,29 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import { cn } from "../lib/utils.js";
3
- /**
4
- * fact-cell — mono-kicker + claim content fill (replaces the retired `.nc-fact-cell`).
5
- *
6
- * A seam-free fill: it drops into a seam-owning grid (which paints the hairline gaps
7
- * between cells), so it draws NO border and is square-cornered. It carries the canvas
8
- * surface, a mono label, and a claim. `surface="ink"` inverts onto the ink role;
9
- * `size="sm"` is the compact 86px action-card rhythm.
10
- *
11
- * Server-renderable: the ink inversion + sm claim sizing are applied by the parent
12
- * to its descendants via `data-slot` descendant selectors (the retired CSS-cascade
13
- * model), so sub-components stay style-light. Token-only; no `dark:` styling.
14
- */
15
- function FactCell({ className, surface = "canvas", size = "default", ...props }) {
16
- return (_jsx("div", { "data-slot": "fact-cell", "data-surface": surface, "data-size": size, className: cn("grid content-center gap-1.5", size === "default" ? "min-h-24 p-6" : "min-h-[86px] p-4", surface === "canvas" && "bg-card", surface === "ink" && [
17
- "bg-primary",
18
- "[&_[data-slot=fact-cell-label]]:text-primary-foreground",
19
- "[&_[data-slot=fact-cell-claim]]:text-primary-foreground",
20
- ], size === "sm" &&
21
- "[&_[data-slot=fact-cell-claim]]:text-[15px] [&_[data-slot=fact-cell-claim]]:leading-5", className), ...props }));
22
- }
23
- function FactCellLabel({ className, ...props }) {
24
- return (_jsx("div", { "data-slot": "fact-cell-label", className: cn("font-mono text-xs uppercase text-muted-foreground", className), ...props }));
25
- }
26
- function FactCellClaim({ className, ...props }) {
27
- return (_jsx("div", { "data-slot": "fact-cell-claim", className: cn("text-lg leading-[1.2] text-foreground", className), ...props }));
28
- }
29
- export { FactCell, FactCellLabel, FactCellClaim };