@pindoba/core-choice 0.0.0-alpha-20260617191010
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/LICENSE +12 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +4 -0
- package/dist/src/connect-choice-item.d.ts +20 -0
- package/dist/src/connect-choice-item.d.ts.map +1 -0
- package/dist/src/connect-choice-item.js +105 -0
- package/dist/src/connect-choice-item.js.map +1 -0
- package/dist/src/connect-choice.d.ts +24 -0
- package/dist/src/connect-choice.d.ts.map +1 -0
- package/dist/src/connect-choice.js +171 -0
- package/dist/src/connect-choice.js.map +1 -0
- package/dist/src/create-choice.d.ts +12 -0
- package/dist/src/create-choice.d.ts.map +1 -0
- package/dist/src/create-choice.js +41 -0
- package/dist/src/create-choice.js.map +1 -0
- package/dist/src/types.d.ts +229 -0
- package/dist/src/types.d.ts.map +1 -0
- package/dist/src/types.js +1 -0
- package/package.json +38 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
Copyright 2025 Eduardo Lopes
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
4
|
+
|
|
5
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
6
|
+
|
|
7
|
+
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
|
8
|
+
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
|
9
|
+
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
|
|
10
|
+
FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|
11
|
+
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
12
|
+
DEALINGS IN THE SOFTWARE.
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { ChoiceApi, ChoiceAppearance, ChoiceBaseProps, ChoiceConfig, ChoiceControlProps, ChoiceEmphasis, ChoiceFeedback, ChoiceIndicatorProps, ChoiceItemApi, ChoiceItemControlApi, ChoiceItemInput, ChoiceOrientation, ChoicePassThrough, ChoiceRootProps, ChoiceSize, ChoiceType, ChoiceValue, ConnectChoiceItemOptions, ConnectChoiceOptions, ElementAttributes, HeadlessChoice } from "./src/types.js";
|
|
2
|
+
import { createChoice } from "./src/create-choice.js";
|
|
3
|
+
import { choiceDefaults, connectChoice } from "./src/connect-choice.js";
|
|
4
|
+
import { choiceItemDefaults, connectChoiceItem } from "./src/connect-choice-item.js";
|
|
5
|
+
export { type ChoiceApi, type ChoiceAppearance, type ChoiceBaseProps, type ChoiceConfig, type ChoiceControlProps, type ChoiceEmphasis, type ChoiceFeedback, type ChoiceIndicatorProps, type ChoiceItemApi, type ChoiceItemControlApi, type ChoiceItemInput, type ChoiceOrientation, type ChoicePassThrough, type ChoiceRootProps, type ChoiceSize, type ChoiceType, type ChoiceValue, type ConnectChoiceItemOptions, type ConnectChoiceOptions, type ElementAttributes, type HeadlessChoice, choiceDefaults, choiceItemDefaults, connectChoice, connectChoiceItem, createChoice };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { createChoice } from "./src/create-choice.js";
|
|
2
|
+
import { choiceItemDefaults, connectChoiceItem } from "./src/connect-choice-item.js";
|
|
3
|
+
import { choiceDefaults, connectChoice } from "./src/connect-choice.js";
|
|
4
|
+
export { choiceDefaults, choiceItemDefaults, connectChoice, connectChoiceItem, createChoice };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { ChoiceItemControlApi, ConnectChoiceItemOptions } from "./types.js";
|
|
2
|
+
|
|
3
|
+
//#region src/connect-choice-item.d.ts
|
|
4
|
+
declare const choiceItemDefaults: {
|
|
5
|
+
readonly type: "radio";
|
|
6
|
+
readonly appearance: "button";
|
|
7
|
+
readonly emphasis: "tertiary";
|
|
8
|
+
readonly groupedEmphasis: "secondary";
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Build the spread bags for one selectable item — the `<Radio>`/`<Checkbox>`
|
|
12
|
+
* control bag, plus an inner `<Card>` bag for `appearance: "card"`.
|
|
13
|
+
*
|
|
14
|
+
* Used directly by slotted-mode `<ChoiceItem>` and re-used by `connectChoice`
|
|
15
|
+
* for items-array mode, so the per-item contract never drifts between the two.
|
|
16
|
+
*/
|
|
17
|
+
declare function connectChoiceItem(options: ConnectChoiceItemOptions): ChoiceItemControlApi;
|
|
18
|
+
//#endregion
|
|
19
|
+
export { choiceItemDefaults, connectChoiceItem };
|
|
20
|
+
//# sourceMappingURL=connect-choice-item.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connect-choice-item.d.ts","names":[],"sources":["../../src/connect-choice-item.ts"],"mappings":";;;cASa,kBAAA;EAAA;;;;;;;;;;;AA6Bb;iBAAgB,iBAAA,CACd,OAAA,EAAS,wBAAA,GACR,oBAAoB"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { choiceStyles } from "@pindoba/styles-choice";
|
|
2
|
+
import { css } from "@pindoba/styled-system/css";
|
|
3
|
+
//#region src/connect-choice-item.ts
|
|
4
|
+
const choiceItemDefaults = {
|
|
5
|
+
type: "radio",
|
|
6
|
+
appearance: "button",
|
|
7
|
+
emphasis: "tertiary",
|
|
8
|
+
groupedEmphasis: "secondary"
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Default colorway per appearance. The segmented `button` fills its whole
|
|
12
|
+
* surface on select, so it stays neutral to avoid a loud block of color; the
|
|
13
|
+
* card surface and the native radio/checkbox/switch indicators are small
|
|
14
|
+
* accents, so they default to the primary colorway (selected ring / dot).
|
|
15
|
+
* Always overridable via the item's / group's `feedback`.
|
|
16
|
+
*/
|
|
17
|
+
function defaultFeedbackFor(appearance) {
|
|
18
|
+
return appearance === "button" ? "neutral" : "primary";
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Build the spread bags for one selectable item — the `<Radio>`/`<Checkbox>`
|
|
22
|
+
* control bag, plus an inner `<Card>` bag for `appearance: "card"`.
|
|
23
|
+
*
|
|
24
|
+
* Used directly by slotted-mode `<ChoiceItem>` and re-used by `connectChoice`
|
|
25
|
+
* for items-array mode, so the per-item contract never drifts between the two.
|
|
26
|
+
*/
|
|
27
|
+
function connectChoiceItem(options) {
|
|
28
|
+
const { type = choiceItemDefaults.type, appearance = choiceItemDefaults.appearance, value, selected = false, disabled, name, emphasis: emphasisProp, feedback: feedbackProp, fullWidth, size, header, footer, id, group = false, hideIndicator = false, passThrough, label: _label, leading: _leading, trailing: _trailing, ...extras } = options;
|
|
29
|
+
const emphasis = emphasisProp ?? (group ? choiceItemDefaults.groupedEmphasis : choiceItemDefaults.emphasis);
|
|
30
|
+
const isCard = appearance === "card";
|
|
31
|
+
const feedback = feedbackProp ?? defaultFeedbackFor(appearance);
|
|
32
|
+
const resolvedId = id ?? (name != null ? `${name}-${value}` : `choice-${value}`);
|
|
33
|
+
if (isCard) {
|
|
34
|
+
const cardProps = {
|
|
35
|
+
as: "label",
|
|
36
|
+
background: "surface.soft",
|
|
37
|
+
emphasis,
|
|
38
|
+
feedback,
|
|
39
|
+
border: "default",
|
|
40
|
+
radius: "inner",
|
|
41
|
+
interactive: true,
|
|
42
|
+
"data-choice-item": "",
|
|
43
|
+
"data-choice-value": value,
|
|
44
|
+
passThrough: { root: { style: css.raw(choiceStyles.raw({ appearance: "card" }).card, passThrough?.card?.style) } }
|
|
45
|
+
};
|
|
46
|
+
if (size != null) cardProps.size = size;
|
|
47
|
+
if (header !== void 0) cardProps.header = header;
|
|
48
|
+
if (footer !== void 0) cardProps.footer = footer;
|
|
49
|
+
const indicatorProps = {
|
|
50
|
+
...extras,
|
|
51
|
+
as: "span",
|
|
52
|
+
appearance: type === "checkbox" ? "checkbox" : "radio",
|
|
53
|
+
value,
|
|
54
|
+
checked: selected,
|
|
55
|
+
id: resolvedId,
|
|
56
|
+
feedback
|
|
57
|
+
};
|
|
58
|
+
if (disabled != null) indicatorProps.disabled = disabled;
|
|
59
|
+
if (name != null) indicatorProps.name = name;
|
|
60
|
+
if (size != null) indicatorProps.size = size;
|
|
61
|
+
if (hideIndicator) indicatorProps.passThrough = { root: { style: {
|
|
62
|
+
position: "absolute",
|
|
63
|
+
width: "1px",
|
|
64
|
+
height: "1px",
|
|
65
|
+
padding: "0",
|
|
66
|
+
margin: "-1px",
|
|
67
|
+
overflow: "hidden",
|
|
68
|
+
clip: "rect(0, 0, 0, 0)",
|
|
69
|
+
whiteSpace: "nowrap",
|
|
70
|
+
borderWidth: "0"
|
|
71
|
+
} } };
|
|
72
|
+
return {
|
|
73
|
+
type,
|
|
74
|
+
appearance,
|
|
75
|
+
cardProps,
|
|
76
|
+
indicatorProps
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
const controlAppearance = appearance === "button" ? "button" : appearance;
|
|
80
|
+
const controlProps = {
|
|
81
|
+
...extras,
|
|
82
|
+
appearance: controlAppearance,
|
|
83
|
+
value,
|
|
84
|
+
checked: selected,
|
|
85
|
+
id: resolvedId,
|
|
86
|
+
emphasis,
|
|
87
|
+
feedback,
|
|
88
|
+
radius: "inner",
|
|
89
|
+
"data-choice-item": "",
|
|
90
|
+
"data-choice-value": value
|
|
91
|
+
};
|
|
92
|
+
if (disabled != null) controlProps.disabled = disabled;
|
|
93
|
+
if (name != null) controlProps.name = name;
|
|
94
|
+
if (fullWidth != null) controlProps.fullWidth = fullWidth;
|
|
95
|
+
if (size != null) controlProps.size = size;
|
|
96
|
+
return {
|
|
97
|
+
type,
|
|
98
|
+
appearance,
|
|
99
|
+
controlProps
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
//#endregion
|
|
103
|
+
export { choiceItemDefaults, connectChoiceItem };
|
|
104
|
+
|
|
105
|
+
//# sourceMappingURL=connect-choice-item.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connect-choice-item.js","names":[],"sources":["../../src/connect-choice-item.ts"],"sourcesContent":["import { css } from \"@pindoba/styled-system/css\";\nimport { choiceStyles } from \"@pindoba/styles-choice\";\nimport type {\n ChoiceControlProps,\n ChoiceIndicatorProps,\n ChoiceItemControlApi,\n ConnectChoiceItemOptions,\n} from \"./types.js\";\n\nexport const choiceItemDefaults = {\n type: \"radio\",\n appearance: \"button\",\n // Emphasis default depends on whether the item is part of a merged `group`:\n // `\"secondary\"` (palette-tinted segments) when grouped so the joined control\n // reads as one surface, otherwise `\"tertiary\"` — the quietest look, plain\n // segments until selected. An explicit `emphasis` always wins.\n emphasis: \"tertiary\",\n groupedEmphasis: \"secondary\",\n} as const;\n\n/**\n * Default colorway per appearance. The segmented `button` fills its whole\n * surface on select, so it stays neutral to avoid a loud block of color; the\n * card surface and the native radio/checkbox/switch indicators are small\n * accents, so they default to the primary colorway (selected ring / dot).\n * Always overridable via the item's / group's `feedback`.\n */\nfunction defaultFeedbackFor(appearance: string): \"neutral\" | \"primary\" {\n return appearance === \"button\" ? \"neutral\" : \"primary\";\n}\n\n/**\n * Build the spread bags for one selectable item — the `<Radio>`/`<Checkbox>`\n * control bag, plus an inner `<Card>` bag for `appearance: \"card\"`.\n *\n * Used directly by slotted-mode `<ChoiceItem>` and re-used by `connectChoice`\n * for items-array mode, so the per-item contract never drifts between the two.\n */\nexport function connectChoiceItem(\n options: ConnectChoiceItemOptions,\n): ChoiceItemControlApi {\n const {\n type = choiceItemDefaults.type,\n appearance = choiceItemDefaults.appearance,\n value,\n selected = false,\n disabled,\n name,\n emphasis: emphasisProp,\n feedback: feedbackProp,\n fullWidth,\n size,\n header,\n footer,\n id,\n group = false,\n hideIndicator = false,\n passThrough,\n // `label`, `leading`, and `trailing` are framework render content consumed\n // by the template (the affix slots of the wrapped Radio/Checkbox), never\n // the control bag — strip them so they don't leak onto the spread.\n label: _label,\n leading: _leading,\n trailing: _trailing,\n ...extras\n } = options;\n\n // Grouped items default to the tinted `secondary`, standalone items to the\n // quieter `tertiary`. An explicit `emphasis` always wins.\n const emphasis =\n emphasisProp ??\n (group ? choiceItemDefaults.groupedEmphasis : choiceItemDefaults.emphasis);\n\n const isCard = appearance === \"card\";\n const feedback = feedbackProp ?? defaultFeedbackFor(appearance);\n\n // Stable per-item id — always set so Astro's Radio (which requires `id`)\n // type-checks and labels associate. Prefers explicit `id`, then `name`-scoped,\n // then a value-derived fallback.\n const resolvedId =\n id ?? (name != null ? `${name}-${value}` : `choice-${value}`);\n\n // ── Card appearance ────────────────────────────────────────────────────\n // The real `Card` is the selectable surface (rendered `as=\"label\"`), and the\n // indicator is a label-less `<Radio>`/`<Checkbox>` (`as=\"span\"`) placed in the\n // Card's Banner leading slot. The Card owns its own padding/layout — Choice\n // only adds cursor + an accent ring on `:has(input:checked)` (CSS-driven, so\n // selection updates at runtime in every framework, Astro included).\n if (isCard) {\n const cardStyle = css.raw(\n choiceStyles.raw({ appearance: \"card\" }).card,\n passThrough?.card?.style,\n );\n // The Card owns its own padding (root `none`, header/content/footer carry\n // size-derived padding) — Choice must NOT add any. We only set the outline\n // border + the data hooks + the cursor/ring style layer.\n const cardProps: Record<string, unknown> = {\n as: \"label\" as const,\n background: \"surface.soft\",\n emphasis,\n feedback,\n border: \"default\",\n // Concentric corners: the card's radius nests inside the Choice\n // container's radius (Panel reads the container's exported\n // `--panel-out-radius`/`--panel-out-padding`). So the card curve tracks\n // the container's curve minus the padding gap.\n radius: \"inner\" as const,\n // Hover/active surface stepping (Panel `interactive`) — the whole card\n // is a control, so it should feel like one.\n interactive: true,\n \"data-choice-item\": \"\",\n \"data-choice-value\": value,\n passThrough: { root: { style: cardStyle } },\n };\n // `size` drives the Card's padding/heading scale too (not just the\n // indicator), so the whole card tracks one scale.\n if (size != null) cardProps.size = size;\n if (header !== undefined) cardProps.header = header;\n if (footer !== undefined) cardProps.footer = footer;\n\n const indicatorProps: ChoiceIndicatorProps = {\n ...extras,\n as: \"span\" as const,\n appearance: type === \"checkbox\" ? \"checkbox\" : \"radio\",\n value,\n checked: selected,\n id: resolvedId,\n feedback,\n };\n if (disabled != null) indicatorProps.disabled = disabled;\n if (name != null) indicatorProps.name = name;\n if (size != null) indicatorProps.size = size;\n // `hideIndicator` keeps the real input (selection + a11y + clickable label\n // stay intact) but visually hides it, so selection reads only from the\n // accent ring. Merge the clip with any consumer card passThrough on input.\n if (hideIndicator) {\n indicatorProps.passThrough = {\n root: {\n style: {\n position: \"absolute\",\n width: \"1px\",\n height: \"1px\",\n padding: \"0\",\n margin: \"-1px\",\n overflow: \"hidden\",\n clip: \"rect(0, 0, 0, 0)\",\n whiteSpace: \"nowrap\",\n borderWidth: \"0\",\n },\n },\n };\n }\n\n return { type, appearance, cardProps, indicatorProps };\n }\n\n // ── Non-card appearances (button / radio / checkbox) ───────────────────\n // Wrap the full `<Radio>`/`<Checkbox>` component via a single control bag.\n const controlAppearance = appearance === \"button\" ? \"button\" : appearance;\n\n const controlProps: ChoiceControlProps = {\n ...extras,\n appearance: controlAppearance,\n value,\n checked: selected,\n id: resolvedId,\n emphasis,\n feedback,\n // Concentric corners: the item surface's radius nests inside the Choice\n // container's radius (the Radio/Checkbox Panel reads the container's\n // exported `--panel-out-radius`/`--panel-out-padding`). So the item curve\n // tracks the container's curve minus the padding gap — mirroring the\n // `radius=\"inner\"` the card appearance already uses.\n radius: \"inner\" as const,\n \"data-choice-item\": \"\",\n \"data-choice-value\": value,\n };\n if (disabled != null) controlProps.disabled = disabled;\n if (name != null) controlProps.name = name;\n if (fullWidth != null) controlProps.fullWidth = fullWidth;\n if (size != null) controlProps.size = size;\n\n return { type, appearance, controlProps };\n}\n"],"mappings":";;;AASA,MAAa,qBAAqB;CAChC,MAAM;CACN,YAAY;CAKZ,UAAU;CACV,iBAAiB;AACnB;;;;;;;;AASA,SAAS,mBAAmB,YAA2C;CACrE,OAAO,eAAe,WAAW,YAAY;AAC/C;;;;;;;;AASA,SAAgB,kBACd,SACsB;CACtB,MAAM,EACJ,OAAO,mBAAmB,MAC1B,aAAa,mBAAmB,YAChC,OACA,WAAW,OACX,UACA,MACA,UAAU,cACV,UAAU,cACV,WACA,MACA,QACA,QACA,IACA,QAAQ,OACR,gBAAgB,OAChB,aAIA,OAAO,QACP,SAAS,UACT,UAAU,WACV,GAAG,WACD;CAIJ,MAAM,WACJ,iBACC,QAAQ,mBAAmB,kBAAkB,mBAAmB;CAEnE,MAAM,SAAS,eAAe;CAC9B,MAAM,WAAW,gBAAgB,mBAAmB,UAAU;CAK9D,MAAM,aACJ,OAAO,QAAQ,OAAO,GAAG,KAAK,GAAG,UAAU,UAAU;CAQvD,IAAI,QAAQ;EAQV,MAAM,YAAqC;GACzC,IAAI;GACJ,YAAY;GACZ;GACA;GACA,QAAQ;GAKR,QAAQ;GAGR,aAAa;GACb,oBAAoB;GACpB,qBAAqB;GACrB,aAAa,EAAE,MAAM,EAAE,OAvBP,IAAI,IACpB,aAAa,IAAI,EAAE,YAAY,OAAO,CAAC,CAAC,CAAC,MACzC,aAAa,MAAM,KAqBmB,EAAE,EAAE;EAC5C;EAGA,IAAI,QAAQ,MAAM,UAAU,OAAO;EACnC,IAAI,WAAW,KAAA,GAAW,UAAU,SAAS;EAC7C,IAAI,WAAW,KAAA,GAAW,UAAU,SAAS;EAE7C,MAAM,iBAAuC;GAC3C,GAAG;GACH,IAAI;GACJ,YAAY,SAAS,aAAa,aAAa;GAC/C;GACA,SAAS;GACT,IAAI;GACJ;EACF;EACA,IAAI,YAAY,MAAM,eAAe,WAAW;EAChD,IAAI,QAAQ,MAAM,eAAe,OAAO;EACxC,IAAI,QAAQ,MAAM,eAAe,OAAO;EAIxC,IAAI,eACF,eAAe,cAAc,EAC3B,MAAM,EACJ,OAAO;GACL,UAAU;GACV,OAAO;GACP,QAAQ;GACR,SAAS;GACT,QAAQ;GACR,UAAU;GACV,MAAM;GACN,YAAY;GACZ,aAAa;EACf,EACF,EACF;EAGF,OAAO;GAAE;GAAM;GAAY;GAAW;EAAe;CACvD;CAIA,MAAM,oBAAoB,eAAe,WAAW,WAAW;CAE/D,MAAM,eAAmC;EACvC,GAAG;EACH,YAAY;EACZ;EACA,SAAS;EACT,IAAI;EACJ;EACA;EAMA,QAAQ;EACR,oBAAoB;EACpB,qBAAqB;CACvB;CACA,IAAI,YAAY,MAAM,aAAa,WAAW;CAC9C,IAAI,QAAQ,MAAM,aAAa,OAAO;CACtC,IAAI,aAAa,MAAM,aAAa,YAAY;CAChD,IAAI,QAAQ,MAAM,aAAa,OAAO;CAEtC,OAAO;EAAE;EAAM;EAAY;CAAa;AAC1C"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { ChoiceApi, ConnectChoiceOptions } from "./types.js";
|
|
2
|
+
|
|
3
|
+
//#region src/connect-choice.d.ts
|
|
4
|
+
declare const choiceDefaults: {
|
|
5
|
+
readonly type: "radio";
|
|
6
|
+
readonly appearance: "button";
|
|
7
|
+
readonly emphasis: "tertiary";
|
|
8
|
+
readonly orientation: "horizontal";
|
|
9
|
+
readonly size: "md";
|
|
10
|
+
readonly background: "surface.deep";
|
|
11
|
+
readonly border: "none";
|
|
12
|
+
readonly shadow: "none";
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Connect Contract v1.1 — the root bag plus a pre-computed `items` array. Each
|
|
16
|
+
* entry carries the spread bags the template needs to render one selectable
|
|
17
|
+
* item: `controlProps` for the `<Radio>`/`<Checkbox>`, and `cardProps` for the
|
|
18
|
+
* inner `<Card>` when `appearance: "card"`. `selectedValues` drives each
|
|
19
|
+
* control's `checked`; re-deriving the array on selection change is cheap.
|
|
20
|
+
*/
|
|
21
|
+
declare function connectChoice(options?: ConnectChoiceOptions): ChoiceApi;
|
|
22
|
+
//#endregion
|
|
23
|
+
export { choiceDefaults, connectChoice };
|
|
24
|
+
//# sourceMappingURL=connect-choice.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connect-choice.d.ts","names":[],"sources":["../../src/connect-choice.ts"],"mappings":";;;cAUa,cAAA;EAAA;;;;;;;;;;;;;;;AA6Eb;iBAAgB,aAAA,CAAc,OAAA,GAAS,oBAAA,GAA4B,SAAS"}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import { connectChoiceItem } from "./connect-choice-item.js";
|
|
2
|
+
import { connectPanel } from "@pindoba/core-panel";
|
|
3
|
+
import { choiceStyles } from "@pindoba/styles-choice";
|
|
4
|
+
//#region src/connect-choice.ts
|
|
5
|
+
const choiceDefaults = {
|
|
6
|
+
type: "radio",
|
|
7
|
+
appearance: "button",
|
|
8
|
+
emphasis: "tertiary",
|
|
9
|
+
orientation: "horizontal",
|
|
10
|
+
size: "md",
|
|
11
|
+
background: "surface.deep",
|
|
12
|
+
border: "none",
|
|
13
|
+
shadow: "none"
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* The container's padding **and** the gap between items both come from this
|
|
17
|
+
* scale, keyed by `size` — they're always equal, and shrink with the size.
|
|
18
|
+
* (An explicit `padding` prop overrides the padding *and* the matching gap.)
|
|
19
|
+
* Kept tight so items sit close to the container edge.
|
|
20
|
+
*/
|
|
21
|
+
const SIZE_SPACE = {
|
|
22
|
+
sm: "4xs",
|
|
23
|
+
md: "3xs",
|
|
24
|
+
lg: "2xs"
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* `appearance: "card"` overrides the tight scale above. Cards are distinct
|
|
28
|
+
* surfaces (not seamless segments), so the gap between them — and the
|
|
29
|
+
* container's framing padding — should match each card's *own* content padding,
|
|
30
|
+
* which equals the size token (sm → 12px, md → 16px, lg → 20px). The segmented
|
|
31
|
+
* `SIZE_SPACE` reads as too cramped once the items are separated cards (the gap
|
|
32
|
+
* looked smaller than the cards' internal padding).
|
|
33
|
+
*/
|
|
34
|
+
const CARD_SIZE_SPACE = {
|
|
35
|
+
sm: "sm",
|
|
36
|
+
md: "md",
|
|
37
|
+
lg: "lg"
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* Container radius for the card appearance — sized roughly to match the larger
|
|
41
|
+
* card padding so the framed surface stays proportionate. The inner cards keep
|
|
42
|
+
* `radius="inner"`, which clamps to `xs` (4px) here at every size.
|
|
43
|
+
*/
|
|
44
|
+
const CARD_RADIUS_BY_SIZE = {
|
|
45
|
+
sm: "lg",
|
|
46
|
+
md: "xl",
|
|
47
|
+
lg: "2xl"
|
|
48
|
+
};
|
|
49
|
+
/**
|
|
50
|
+
* The container radius is sized so that `radius − padding` lands as close as the
|
|
51
|
+
* radii token grid allows on the item's own corner radius at every size — so
|
|
52
|
+
* segmented buttons (whose radius comes from the size scale: xs/sm/md = 4/6/8px)
|
|
53
|
+
* nest concentrically inside the container. With the tight SIZE_SPACE padding
|
|
54
|
+
* (4xs/3xs/2xs = 2/4/6px) the exact concentric radius would be item + padding =
|
|
55
|
+
* 6/10/14px; 10px and 14px aren't tokens, so md/lg round to the nearest token
|
|
56
|
+
* (each size maps to its eponymous radius — sm/md/lg = 6/8/12px):
|
|
57
|
+
* sm → sm (6px) − 4xs (2px) = 4px = button radius @ sm (exact)
|
|
58
|
+
* md → md (8px) − 3xs (4px) = 4px ≈ button radius @ md (6px, ~2px tight)
|
|
59
|
+
* lg → lg (12px) − 2xs (6px) = 6px ≈ button radius @ lg (8px, ~2px tight)
|
|
60
|
+
*/
|
|
61
|
+
const RADIUS_BY_SIZE = {
|
|
62
|
+
sm: "sm",
|
|
63
|
+
md: "md",
|
|
64
|
+
lg: "lg"
|
|
65
|
+
};
|
|
66
|
+
/**
|
|
67
|
+
* Connect Contract v1.1 — the root bag plus a pre-computed `items` array. Each
|
|
68
|
+
* entry carries the spread bags the template needs to render one selectable
|
|
69
|
+
* item: `controlProps` for the `<Radio>`/`<Checkbox>`, and `cardProps` for the
|
|
70
|
+
* inner `<Card>` when `appearance: "card"`. `selectedValues` drives each
|
|
71
|
+
* control's `checked`; re-deriving the array on selection change is cheap.
|
|
72
|
+
*/
|
|
73
|
+
function connectChoice(options = {}) {
|
|
74
|
+
const { type = choiceDefaults.type, appearance = choiceDefaults.appearance, orientation = choiceDefaults.orientation, columns, size = choiceDefaults.size, fullWidth, feedback, emphasis: emphasisProp, name, group = false, background = choiceDefaults.background, border = choiceDefaults.border, radius: radiusProp, padding, shadow = choiceDefaults.shadow, selectedValues = [], items = [], disabled, hideIndicator, class: className, passThrough, ...rest } = options;
|
|
75
|
+
const classes = choiceStyles.raw({
|
|
76
|
+
orientation,
|
|
77
|
+
appearance,
|
|
78
|
+
fullWidth,
|
|
79
|
+
size
|
|
80
|
+
});
|
|
81
|
+
const role = type === "radio" ? "radiogroup" : "group";
|
|
82
|
+
const emphasis = emphasisProp ?? (group ? "secondary" : choiceDefaults.emphasis);
|
|
83
|
+
const isCardAppearance = appearance === "card";
|
|
84
|
+
const spaceToken = padding ?? (isCardAppearance ? CARD_SIZE_SPACE[size] : SIZE_SPACE[size]);
|
|
85
|
+
const gapValue = spaceToken === "none" ? "0" : spaceToken;
|
|
86
|
+
const radius = radiusProp ?? (isCardAppearance ? CARD_RADIUS_BY_SIZE[size] : RADIUS_BY_SIZE[size]);
|
|
87
|
+
const gridTemplate = columns == null ? void 0 : columns === "auto" ? "repeat(auto-fit, minmax(min(100%, 14rem), 1fr))" : `repeat(${columns}, minmax(0, 1fr))`;
|
|
88
|
+
const gridStyle = gridTemplate ? `display:grid;grid-template-columns:${gridTemplate}` : void 0;
|
|
89
|
+
const userStyle = typeof rest.style === "string" ? rest.style : void 0;
|
|
90
|
+
const rootStyle = gridStyle ? [gridStyle, userStyle].filter(Boolean).join(";") : rest.style;
|
|
91
|
+
const itemApis = items.map((item) => {
|
|
92
|
+
const { value, label, disabled: itemDisabled, header, footer, leading, trailing, ...extras } = item;
|
|
93
|
+
const built = connectChoiceItem({
|
|
94
|
+
type,
|
|
95
|
+
appearance,
|
|
96
|
+
value,
|
|
97
|
+
label,
|
|
98
|
+
selected: selectedValues.includes(value),
|
|
99
|
+
disabled: disabled || itemDisabled,
|
|
100
|
+
name,
|
|
101
|
+
emphasis,
|
|
102
|
+
feedback,
|
|
103
|
+
fullWidth,
|
|
104
|
+
size,
|
|
105
|
+
header,
|
|
106
|
+
footer,
|
|
107
|
+
hideIndicator,
|
|
108
|
+
passThrough,
|
|
109
|
+
...extras
|
|
110
|
+
});
|
|
111
|
+
return {
|
|
112
|
+
id: value,
|
|
113
|
+
value,
|
|
114
|
+
...label !== void 0 ? { label } : {},
|
|
115
|
+
...leading !== void 0 ? { leading } : {},
|
|
116
|
+
...trailing !== void 0 ? { trailing } : {},
|
|
117
|
+
...built.controlProps ? { controlProps: built.controlProps } : {},
|
|
118
|
+
...built.cardProps ? { cardProps: built.cardProps } : {},
|
|
119
|
+
...built.indicatorProps ? { indicatorProps: built.indicatorProps } : {}
|
|
120
|
+
};
|
|
121
|
+
});
|
|
122
|
+
const panelApi = connectPanel({
|
|
123
|
+
dataComponent: "choice",
|
|
124
|
+
dataAttrs: {
|
|
125
|
+
"choice-root": "",
|
|
126
|
+
type,
|
|
127
|
+
appearance,
|
|
128
|
+
...name != null ? { "choice-name": name } : {},
|
|
129
|
+
...group ? { "choice-group": "" } : {}
|
|
130
|
+
},
|
|
131
|
+
background,
|
|
132
|
+
border,
|
|
133
|
+
radius,
|
|
134
|
+
padding: spaceToken,
|
|
135
|
+
shadow,
|
|
136
|
+
feedback,
|
|
137
|
+
emphasis,
|
|
138
|
+
inheritedStyle: {
|
|
139
|
+
...classes.root,
|
|
140
|
+
gap: gapValue
|
|
141
|
+
},
|
|
142
|
+
passThrough: { root: {
|
|
143
|
+
style: passThrough?.root?.style,
|
|
144
|
+
props: passThrough?.root?.props
|
|
145
|
+
} },
|
|
146
|
+
class: className != null ? String(className) : void 0,
|
|
147
|
+
role,
|
|
148
|
+
"aria-orientation": orientation,
|
|
149
|
+
...rest,
|
|
150
|
+
...rootStyle != null ? { style: rootStyle } : {}
|
|
151
|
+
});
|
|
152
|
+
const groupProps = group ? {
|
|
153
|
+
variant: "controls",
|
|
154
|
+
orientation,
|
|
155
|
+
size,
|
|
156
|
+
feedback,
|
|
157
|
+
fullWidth
|
|
158
|
+
} : void 0;
|
|
159
|
+
return {
|
|
160
|
+
rootProps: panelApi.rootProps,
|
|
161
|
+
type,
|
|
162
|
+
appearance,
|
|
163
|
+
items: itemApis,
|
|
164
|
+
group,
|
|
165
|
+
...groupProps ? { groupProps } : {}
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
//#endregion
|
|
169
|
+
export { choiceDefaults, connectChoice };
|
|
170
|
+
|
|
171
|
+
//# sourceMappingURL=connect-choice.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connect-choice.js","names":[],"sources":["../../src/connect-choice.ts"],"sourcesContent":["import { connectPanel } from \"@pindoba/core-panel\";\nimport { choiceStyles } from \"@pindoba/styles-choice\";\nimport { connectChoiceItem } from \"./connect-choice-item.js\";\nimport type {\n ChoiceApi,\n ChoiceItemApi,\n ChoiceRootProps,\n ConnectChoiceOptions,\n} from \"./types.js\";\n\nexport const choiceDefaults = {\n type: \"radio\",\n appearance: \"button\",\n emphasis: \"tertiary\",\n orientation: \"horizontal\",\n size: \"md\",\n // Root-surface defaults — the container reads as one grouped surface out of\n // the box (a deep surface + muted outline). `radius` is size-derived (see\n // RADIUS_BY_SIZE). Override any of them (e.g. `background=\"transparent\"`) to\n // drop the framing.\n background: \"surface.deep\",\n border: \"none\",\n shadow: \"none\",\n} as const;\n\n/**\n * The container's padding **and** the gap between items both come from this\n * scale, keyed by `size` — they're always equal, and shrink with the size.\n * (An explicit `padding` prop overrides the padding *and* the matching gap.)\n * Kept tight so items sit close to the container edge.\n */\nconst SIZE_SPACE = {\n sm: \"4xs\",\n md: \"3xs\",\n lg: \"2xs\",\n} as const;\n\n/**\n * `appearance: \"card\"` overrides the tight scale above. Cards are distinct\n * surfaces (not seamless segments), so the gap between them — and the\n * container's framing padding — should match each card's *own* content padding,\n * which equals the size token (sm → 12px, md → 16px, lg → 20px). The segmented\n * `SIZE_SPACE` reads as too cramped once the items are separated cards (the gap\n * looked smaller than the cards' internal padding).\n */\nconst CARD_SIZE_SPACE = {\n sm: \"sm\",\n md: \"md\",\n lg: \"lg\",\n} as const;\n\n/**\n * Container radius for the card appearance — sized roughly to match the larger\n * card padding so the framed surface stays proportionate. The inner cards keep\n * `radius=\"inner\"`, which clamps to `xs` (4px) here at every size.\n */\nconst CARD_RADIUS_BY_SIZE = {\n sm: \"lg\",\n md: \"xl\",\n lg: \"2xl\",\n} as const;\n\n/**\n * The container radius is sized so that `radius − padding` lands as close as the\n * radii token grid allows on the item's own corner radius at every size — so\n * segmented buttons (whose radius comes from the size scale: xs/sm/md = 4/6/8px)\n * nest concentrically inside the container. With the tight SIZE_SPACE padding\n * (4xs/3xs/2xs = 2/4/6px) the exact concentric radius would be item + padding =\n * 6/10/14px; 10px and 14px aren't tokens, so md/lg round to the nearest token\n * (each size maps to its eponymous radius — sm/md/lg = 6/8/12px):\n * sm → sm (6px) − 4xs (2px) = 4px = button radius @ sm (exact)\n * md → md (8px) − 3xs (4px) = 4px ≈ button radius @ md (6px, ~2px tight)\n * lg → lg (12px) − 2xs (6px) = 6px ≈ button radius @ lg (8px, ~2px tight)\n */\nconst RADIUS_BY_SIZE = {\n sm: \"sm\",\n md: \"md\",\n lg: \"lg\",\n} as const;\n\n/**\n * Connect Contract v1.1 — the root bag plus a pre-computed `items` array. Each\n * entry carries the spread bags the template needs to render one selectable\n * item: `controlProps` for the `<Radio>`/`<Checkbox>`, and `cardProps` for the\n * inner `<Card>` when `appearance: \"card\"`. `selectedValues` drives each\n * control's `checked`; re-deriving the array on selection change is cheap.\n */\nexport function connectChoice(options: ConnectChoiceOptions = {}): ChoiceApi {\n const {\n type = choiceDefaults.type,\n appearance = choiceDefaults.appearance,\n orientation = choiceDefaults.orientation,\n columns,\n size = choiceDefaults.size,\n fullWidth,\n feedback,\n emphasis: emphasisProp,\n name,\n group = false,\n background = choiceDefaults.background,\n border = choiceDefaults.border,\n radius: radiusProp,\n padding,\n shadow = choiceDefaults.shadow,\n selectedValues = [],\n items = [],\n disabled,\n hideIndicator,\n class: className,\n passThrough,\n ...rest\n } = options;\n\n const classes = choiceStyles.raw({\n orientation,\n appearance,\n fullWidth,\n size,\n });\n const role = type === \"radio\" ? \"radiogroup\" : \"group\";\n\n // Emphasis default depends on grouping. A merged group reads as one segmented\n // control (shared dividers + a single flush outline), where `secondary` —\n // palette-tinted segments — holds together best; standalone (ungrouped) items\n // default to the quieter `tertiary`. An explicit `emphasis` always wins.\n const emphasis =\n emphasisProp ?? (group ? \"secondary\" : choiceDefaults.emphasis);\n\n // Padding and gap share one spacing value so the inner spacing reads evenly.\n // It scales with `size` (smaller size → tighter), unless an explicit\n // `padding` prop overrides it (then the gap follows that too). The padding\n // rides on Panel's own `padding` variant (so it exports `--panel-out-padding`\n // and a child card's `radius=\"inner\"` can compute concentric corners); the\n // gap mirrors it via `inheritedStyle`. `\"none\"` → 0 gap.\n const isCardAppearance = appearance === \"card\";\n const spaceToken =\n padding ?? (isCardAppearance ? CARD_SIZE_SPACE[size] : SIZE_SPACE[size]);\n const gapValue = spaceToken === \"none\" ? \"0\" : spaceToken;\n const radius =\n radiusProp ??\n (isCardAppearance ? CARD_RADIUS_BY_SIZE[size] : RADIUS_BY_SIZE[size]);\n\n // `columns` overrides the flex flow with a CSS grid. We apply it as an inline\n // `style` (rather than a Panda class) because the column count is dynamic —\n // an arbitrary `repeat(n, …)` value can't be statically extracted, and inline\n // style is on the connect lint allowlist. The recipe's `gap` still applies.\n const gridTemplate =\n columns == null\n ? undefined\n : columns === \"auto\"\n ? \"repeat(auto-fit, minmax(min(100%, 14rem), 1fr))\"\n : `repeat(${columns}, minmax(0, 1fr))`;\n const gridStyle = gridTemplate\n ? `display:grid;grid-template-columns:${gridTemplate}`\n : undefined;\n const userStyle = typeof rest.style === \"string\" ? rest.style : undefined;\n const rootStyle = gridStyle\n ? [gridStyle, userStyle].filter(Boolean).join(\";\")\n : rest.style;\n\n const itemApis: ChoiceItemApi[] = items.map((item) => {\n const {\n value,\n label,\n disabled: itemDisabled,\n header,\n footer,\n // `leading`/`trailing` are framework render content (Snippet / ReactNode /\n // slot) forwarded to the wrapped Radio/Checkbox's affix slots — like\n // `label`, they never belong on a `*Props` bag, so pull them out here and\n // surface them on the item API for the template to spread as content.\n leading,\n trailing,\n ...extras\n } = item;\n const built = connectChoiceItem({\n type,\n appearance,\n value,\n label,\n selected: selectedValues.includes(value),\n disabled: disabled || itemDisabled,\n name,\n emphasis,\n feedback,\n fullWidth,\n size,\n header,\n footer,\n hideIndicator,\n passThrough,\n ...extras,\n });\n return {\n id: value,\n value,\n ...(label !== undefined ? { label } : {}),\n ...(leading !== undefined ? { leading } : {}),\n ...(trailing !== undefined ? { trailing } : {}),\n ...(built.controlProps ? { controlProps: built.controlProps } : {}),\n ...(built.cardProps ? { cardProps: built.cardProps } : {}),\n ...(built.indicatorProps ? { indicatorProps: built.indicatorProps } : {}),\n };\n });\n\n // The group container is a Panel, so consumers can paint a surface\n // (background/border/radius/padding/shadow + feedback/emphasis colorway) and\n // have the whole set read as \"one\". The choice recipe's `root` slot (flex\n // layout / gap / orientation / fullWidth) rides in as `inheritedStyle`; the\n // Panel composes recipe → inheritedStyle → passThrough.style → class.\n // Borderless dead space: the Panel reserves a 1px border for layout\n // stability, but auto-collapses it for a non-interactive borderless panel —\n // which the choice container is when `border=\"none\"` (the default) — so we\n // don't add 2px around the group. A visible `border` keeps its 1px.\n const panelApi = connectPanel({\n dataComponent: \"choice\",\n dataAttrs: {\n \"choice-root\": \"\",\n type,\n appearance,\n ...(name != null ? { \"choice-name\": name } : {}),\n ...(group ? { \"choice-group\": \"\" } : {}),\n },\n background,\n border,\n radius,\n padding: spaceToken,\n shadow,\n feedback,\n emphasis,\n inheritedStyle: { ...classes.root, gap: gapValue },\n passThrough: {\n root: {\n style: passThrough?.root?.style,\n props: passThrough?.root?.props,\n },\n },\n class: className != null ? String(className) : undefined,\n role,\n \"aria-orientation\": orientation,\n ...rest,\n ...(rootStyle != null ? { style: rootStyle } : {}),\n });\n\n // Props for the optional `<Group>` wrapper. Group is itself a Panel and owns\n // the merged-control chrome (dividers / flush outline) keyed off each item's\n // `data-component`. We forward the shared geometry so the merge matches.\n const groupProps = group\n ? {\n variant: \"controls\" as const,\n orientation,\n size,\n feedback,\n fullWidth,\n // The join-group is structural only — Choice's root Panel owns the\n // frame (border/background/padding). The Group is a non-interactive,\n // borderless Panel, so it auto-collapses its reserved 1px border (no\n // box-height bloat); the visible outline comes entirely from the joined\n // children's own borders.\n }\n : undefined;\n\n return {\n rootProps: panelApi.rootProps as ChoiceRootProps,\n type,\n appearance,\n items: itemApis,\n group,\n ...(groupProps ? { groupProps } : {}),\n };\n}\n"],"mappings":";;;;AAUA,MAAa,iBAAiB;CAC5B,MAAM;CACN,YAAY;CACZ,UAAU;CACV,aAAa;CACb,MAAM;CAKN,YAAY;CACZ,QAAQ;CACR,QAAQ;AACV;;;;;;;AAQA,MAAM,aAAa;CACjB,IAAI;CACJ,IAAI;CACJ,IAAI;AACN;;;;;;;;;AAUA,MAAM,kBAAkB;CACtB,IAAI;CACJ,IAAI;CACJ,IAAI;AACN;;;;;;AAOA,MAAM,sBAAsB;CAC1B,IAAI;CACJ,IAAI;CACJ,IAAI;AACN;;;;;;;;;;;;;AAcA,MAAM,iBAAiB;CACrB,IAAI;CACJ,IAAI;CACJ,IAAI;AACN;;;;;;;;AASA,SAAgB,cAAc,UAAgC,CAAC,GAAc;CAC3E,MAAM,EACJ,OAAO,eAAe,MACtB,aAAa,eAAe,YAC5B,cAAc,eAAe,aAC7B,SACA,OAAO,eAAe,MACtB,WACA,UACA,UAAU,cACV,MACA,QAAQ,OACR,aAAa,eAAe,YAC5B,SAAS,eAAe,QACxB,QAAQ,YACR,SACA,SAAS,eAAe,QACxB,iBAAiB,CAAC,GAClB,QAAQ,CAAC,GACT,UACA,eACA,OAAO,WACP,aACA,GAAG,SACD;CAEJ,MAAM,UAAU,aAAa,IAAI;EAC/B;EACA;EACA;EACA;CACF,CAAC;CACD,MAAM,OAAO,SAAS,UAAU,eAAe;CAM/C,MAAM,WACJ,iBAAiB,QAAQ,cAAc,eAAe;CAQxD,MAAM,mBAAmB,eAAe;CACxC,MAAM,aACJ,YAAY,mBAAmB,gBAAgB,QAAQ,WAAW;CACpE,MAAM,WAAW,eAAe,SAAS,MAAM;CAC/C,MAAM,SACJ,eACC,mBAAmB,oBAAoB,QAAQ,eAAe;CAMjE,MAAM,eACJ,WAAW,OACP,KAAA,IACA,YAAY,SACV,oDACA,UAAU,QAAQ;CAC1B,MAAM,YAAY,eACd,sCAAsC,iBACtC,KAAA;CACJ,MAAM,YAAY,OAAO,KAAK,UAAU,WAAW,KAAK,QAAQ,KAAA;CAChE,MAAM,YAAY,YACd,CAAC,WAAW,SAAS,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG,IAC/C,KAAK;CAET,MAAM,WAA4B,MAAM,KAAK,SAAS;EACpD,MAAM,EACJ,OACA,OACA,UAAU,cACV,QACA,QAKA,SACA,UACA,GAAG,WACD;EACJ,MAAM,QAAQ,kBAAkB;GAC9B;GACA;GACA;GACA;GACA,UAAU,eAAe,SAAS,KAAK;GACvC,UAAU,YAAY;GACtB;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA,GAAG;EACL,CAAC;EACD,OAAO;GACL,IAAI;GACJ;GACA,GAAI,UAAU,KAAA,IAAY,EAAE,MAAM,IAAI,CAAC;GACvC,GAAI,YAAY,KAAA,IAAY,EAAE,QAAQ,IAAI,CAAC;GAC3C,GAAI,aAAa,KAAA,IAAY,EAAE,SAAS,IAAI,CAAC;GAC7C,GAAI,MAAM,eAAe,EAAE,cAAc,MAAM,aAAa,IAAI,CAAC;GACjE,GAAI,MAAM,YAAY,EAAE,WAAW,MAAM,UAAU,IAAI,CAAC;GACxD,GAAI,MAAM,iBAAiB,EAAE,gBAAgB,MAAM,eAAe,IAAI,CAAC;EACzE;CACF,CAAC;CAWD,MAAM,WAAW,aAAa;EAC5B,eAAe;EACf,WAAW;GACT,eAAe;GACf;GACA;GACA,GAAI,QAAQ,OAAO,EAAE,eAAe,KAAK,IAAI,CAAC;GAC9C,GAAI,QAAQ,EAAE,gBAAgB,GAAG,IAAI,CAAC;EACxC;EACA;EACA;EACA;EACA,SAAS;EACT;EACA;EACA;EACA,gBAAgB;GAAE,GAAG,QAAQ;GAAM,KAAK;EAAS;EACjD,aAAa,EACX,MAAM;GACJ,OAAO,aAAa,MAAM;GAC1B,OAAO,aAAa,MAAM;EAC5B,EACF;EACA,OAAO,aAAa,OAAO,OAAO,SAAS,IAAI,KAAA;EAC/C;EACA,oBAAoB;EACpB,GAAG;EACH,GAAI,aAAa,OAAO,EAAE,OAAO,UAAU,IAAI,CAAC;CAClD,CAAC;CAKD,MAAM,aAAa,QACf;EACE,SAAS;EACT;EACA;EACA;EACA;CAMF,IACA,KAAA;CAEJ,OAAO;EACL,WAAW,SAAS;EACpB;EACA;EACA,OAAO;EACP;EACA,GAAI,aAAa,EAAE,WAAW,IAAI,CAAC;CACrC;AACF"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { ChoiceConfig, HeadlessChoice } from "./types.js";
|
|
2
|
+
|
|
3
|
+
//#region src/create-choice.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Headless selection state for Choice. Mirrors `createAccordion`: a nanostores
|
|
6
|
+
* atom holds the selected value set; external controlled changes are pushed in
|
|
7
|
+
* via `setValue`. `radio` keeps a single value; `checkbox` toggles membership.
|
|
8
|
+
*/
|
|
9
|
+
declare function createChoice(config?: ChoiceConfig): HeadlessChoice;
|
|
10
|
+
//#endregion
|
|
11
|
+
export { createChoice };
|
|
12
|
+
//# sourceMappingURL=create-choice.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-choice.d.ts","names":[],"sources":["../../src/create-choice.ts"],"mappings":";;;;;AAQA;;;iBAAgB,YAAA,CAAa,MAAA,GAAQ,YAAA,GAAoB,cAAc"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { atom } from "nanostores";
|
|
2
|
+
//#region src/create-choice.ts
|
|
3
|
+
/**
|
|
4
|
+
* Headless selection state for Choice. Mirrors `createAccordion`: a nanostores
|
|
5
|
+
* atom holds the selected value set; external controlled changes are pushed in
|
|
6
|
+
* via `setValue`. `radio` keeps a single value; `checkbox` toggles membership.
|
|
7
|
+
*/
|
|
8
|
+
function createChoice(config = {}) {
|
|
9
|
+
function cfg(key) {
|
|
10
|
+
return config[key];
|
|
11
|
+
}
|
|
12
|
+
const $value = atom([...cfg("value") ?? cfg("defaultValue") ?? []]);
|
|
13
|
+
function setValue(next) {
|
|
14
|
+
const prev = $value.get();
|
|
15
|
+
if (prev.length === next.length && prev.every((v, i) => v === next[i])) return;
|
|
16
|
+
$value.set(next);
|
|
17
|
+
cfg("onValueChange")?.([...next]);
|
|
18
|
+
}
|
|
19
|
+
function isSelected(value) {
|
|
20
|
+
return $value.get().includes(value);
|
|
21
|
+
}
|
|
22
|
+
function select(value) {
|
|
23
|
+
if (cfg("disabled")) return;
|
|
24
|
+
const type = cfg("type") ?? "radio";
|
|
25
|
+
const current = $value.get();
|
|
26
|
+
if (type === "radio") setValue([value]);
|
|
27
|
+
else setValue(current.includes(value) ? current.filter((v) => v !== value) : [...current, value]);
|
|
28
|
+
}
|
|
29
|
+
function destroy() {}
|
|
30
|
+
return {
|
|
31
|
+
$value,
|
|
32
|
+
select,
|
|
33
|
+
isSelected,
|
|
34
|
+
setValue,
|
|
35
|
+
destroy
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
//#endregion
|
|
39
|
+
export { createChoice };
|
|
40
|
+
|
|
41
|
+
//# sourceMappingURL=create-choice.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-choice.js","names":[],"sources":["../../src/create-choice.ts"],"sourcesContent":["import { atom } from \"nanostores\";\nimport type { ChoiceConfig, ChoiceValue, HeadlessChoice } from \"./types.js\";\n\n/**\n * Headless selection state for Choice. Mirrors `createAccordion`: a nanostores\n * atom holds the selected value set; external controlled changes are pushed in\n * via `setValue`. `radio` keeps a single value; `checkbox` toggles membership.\n */\nexport function createChoice(config: ChoiceConfig = {}): HeadlessChoice {\n function cfg<K extends keyof ChoiceConfig>(key: K): ChoiceConfig[K] {\n return config[key];\n }\n\n const initial = cfg(\"value\") ?? cfg(\"defaultValue\") ?? [];\n const $value = atom<ChoiceValue[]>([...initial]);\n\n function setValue(next: ChoiceValue[]) {\n const prev = $value.get();\n if (prev.length === next.length && prev.every((v, i) => v === next[i])) {\n return;\n }\n $value.set(next);\n cfg(\"onValueChange\")?.([...next]);\n }\n\n function isSelected(value: ChoiceValue) {\n return $value.get().includes(value);\n }\n\n function select(value: ChoiceValue) {\n if (cfg(\"disabled\")) return;\n const type = cfg(\"type\") ?? \"radio\";\n const current = $value.get();\n if (type === \"radio\") {\n // Native radios don't deselect on re-click — replacing with the same\n // single value is a no-op handled by setValue's equality guard.\n setValue([value]);\n } else {\n setValue(\n current.includes(value)\n ? current.filter((v) => v !== value)\n : [...current, value],\n );\n }\n }\n\n function destroy() {\n // No listeners to detach; atom is GC'd with the host.\n }\n\n return { $value, select, isSelected, setValue, destroy };\n}\n"],"mappings":";;;;;;;AAQA,SAAgB,aAAa,SAAuB,CAAC,GAAmB;CACtE,SAAS,IAAkC,KAAyB;EAClE,OAAO,OAAO;CAChB;CAGA,MAAM,SAAS,KAAoB,CAAC,GADpB,IAAI,OAAO,KAAK,IAAI,cAAc,KAAK,CAAC,CACV,CAAC;CAE/C,SAAS,SAAS,MAAqB;EACrC,MAAM,OAAO,OAAO,IAAI;EACxB,IAAI,KAAK,WAAW,KAAK,UAAU,KAAK,OAAO,GAAG,MAAM,MAAM,KAAK,EAAE,GACnE;EAEF,OAAO,IAAI,IAAI;EACf,IAAI,eAAe,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;CAClC;CAEA,SAAS,WAAW,OAAoB;EACtC,OAAO,OAAO,IAAI,CAAC,CAAC,SAAS,KAAK;CACpC;CAEA,SAAS,OAAO,OAAoB;EAClC,IAAI,IAAI,UAAU,GAAG;EACrB,MAAM,OAAO,IAAI,MAAM,KAAK;EAC5B,MAAM,UAAU,OAAO,IAAI;EAC3B,IAAI,SAAS,SAGX,SAAS,CAAC,KAAK,CAAC;OAEhB,SACE,QAAQ,SAAS,KAAK,IAClB,QAAQ,QAAQ,MAAM,MAAM,KAAK,IACjC,CAAC,GAAG,SAAS,KAAK,CACxB;CAEJ;CAEA,SAAS,UAAU,CAEnB;CAEA,OAAO;EAAE;EAAQ;EAAQ;EAAY;EAAU;CAAQ;AACzD"}
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
import { WritableAtom } from "nanostores";
|
|
2
|
+
import { PanelBackground, PanelBorder, PanelPadding, PanelRadius, PanelShadow } from "@pindoba/core-panel";
|
|
3
|
+
import { ChoiceStyleProps } from "@pindoba/styles-choice";
|
|
4
|
+
import { SystemStyleObject } from "@pindoba/styled-system/types";
|
|
5
|
+
|
|
6
|
+
//#region src/types.d.ts
|
|
7
|
+
type ElementAttributes = Partial<Record<string, unknown>>;
|
|
8
|
+
/**
|
|
9
|
+
* Semantic selection behavior:
|
|
10
|
+
* - `radio` → single mutually-exclusive selection.
|
|
11
|
+
* - `checkbox` → independent multi-selection.
|
|
12
|
+
*/
|
|
13
|
+
type ChoiceType = "radio" | "checkbox";
|
|
14
|
+
/**
|
|
15
|
+
* Visual treatment of each selectable item. Maps onto the wrapped
|
|
16
|
+
* Radio/Checkbox `appearance`:
|
|
17
|
+
* - `radio` / `checkbox` → native indicator.
|
|
18
|
+
* - `button` → segmented-control look.
|
|
19
|
+
* - `card` → button surface wrapping an inner Card.
|
|
20
|
+
*/
|
|
21
|
+
type ChoiceAppearance = "button" | "card" | "radio" | "checkbox";
|
|
22
|
+
type ChoiceValue = string;
|
|
23
|
+
type ChoiceOrientation = NonNullable<ChoiceStyleProps["orientation"]>;
|
|
24
|
+
type ChoiceSize = NonNullable<ChoiceStyleProps["size"]>;
|
|
25
|
+
type ChoiceFeedback = "neutral" | "primary" | "success" | "warning" | "danger" | "inherit";
|
|
26
|
+
type ChoiceEmphasis = "primary" | "secondary" | "tertiary";
|
|
27
|
+
interface ChoiceSlotPassThrough<T = ElementAttributes> {
|
|
28
|
+
style?: SystemStyleObject;
|
|
29
|
+
props?: T;
|
|
30
|
+
}
|
|
31
|
+
interface ChoicePassThrough<RootElementAttributes = ElementAttributes> {
|
|
32
|
+
/** The group container element. */
|
|
33
|
+
root?: ChoiceSlotPassThrough<RootElementAttributes>;
|
|
34
|
+
/**
|
|
35
|
+
* Style merged into each `appearance: "card"` control's root slot, on top of
|
|
36
|
+
* the recipe's card layer. No effect for other appearances.
|
|
37
|
+
*/
|
|
38
|
+
card?: ChoiceSlotPassThrough;
|
|
39
|
+
}
|
|
40
|
+
interface ChoiceConfig {
|
|
41
|
+
type?: ChoiceType;
|
|
42
|
+
value?: ChoiceValue[];
|
|
43
|
+
defaultValue?: ChoiceValue[];
|
|
44
|
+
disabled?: boolean;
|
|
45
|
+
onValueChange?: (value: ChoiceValue[]) => void;
|
|
46
|
+
}
|
|
47
|
+
interface HeadlessChoice {
|
|
48
|
+
$value: WritableAtom<ChoiceValue[]>;
|
|
49
|
+
/** Radio: replace selection. Checkbox: toggle membership. */
|
|
50
|
+
select: (value: ChoiceValue) => void;
|
|
51
|
+
isSelected: (value: ChoiceValue) => boolean;
|
|
52
|
+
/** Push an externally-controlled value set in. */
|
|
53
|
+
setValue: (next: ChoiceValue[]) => void;
|
|
54
|
+
destroy: () => void;
|
|
55
|
+
}
|
|
56
|
+
interface ChoiceItemInput {
|
|
57
|
+
value: ChoiceValue;
|
|
58
|
+
/** Label text for non-card appearances. */
|
|
59
|
+
label?: string;
|
|
60
|
+
disabled?: boolean;
|
|
61
|
+
/** Card-appearance content forwarded to the inner `<Card>`. */
|
|
62
|
+
header?: unknown;
|
|
63
|
+
footer?: unknown;
|
|
64
|
+
/**
|
|
65
|
+
* Affix content forwarded to the wrapped Radio/Checkbox's `leading` slot
|
|
66
|
+
* (non-card appearances). Framework render content (Snippet / ReactNode /
|
|
67
|
+
* slot) — never lands on a `*Props` bag.
|
|
68
|
+
*/
|
|
69
|
+
leading?: unknown;
|
|
70
|
+
/** Affix content forwarded to the wrapped Radio/Checkbox's `trailing` slot. */
|
|
71
|
+
trailing?: unknown;
|
|
72
|
+
/** Per-item extras flow onto the control bag (HTML attrs, data-*, aria-*). */
|
|
73
|
+
[key: string]: unknown;
|
|
74
|
+
}
|
|
75
|
+
interface ChoiceBaseProps<RootElementAttributes = ElementAttributes> {
|
|
76
|
+
type?: ChoiceType;
|
|
77
|
+
appearance?: ChoiceAppearance;
|
|
78
|
+
orientation?: ChoiceOrientation;
|
|
79
|
+
/**
|
|
80
|
+
* Lay items out in a CSS grid instead of the orientation's flex flow:
|
|
81
|
+
* - a number → that many equal columns (`repeat(n, minmax(0, 1fr))`).
|
|
82
|
+
* - `"auto"` → a responsive auto-fit grid that wraps as space allows.
|
|
83
|
+
* Unset keeps the flex flow (horizontal wraps, vertical stacks). Great for
|
|
84
|
+
* laying out cards.
|
|
85
|
+
*/
|
|
86
|
+
columns?: number | "auto";
|
|
87
|
+
size?: ChoiceSize;
|
|
88
|
+
fullWidth?: boolean;
|
|
89
|
+
feedback?: ChoiceFeedback;
|
|
90
|
+
/**
|
|
91
|
+
* Emphasis applied to every item in the group. The default depends on `group`:
|
|
92
|
+
* `"secondary"` (palette-tinted segments) when `group` is true so the merged
|
|
93
|
+
* control reads as one surface, otherwise `"tertiary"` — the quietest look,
|
|
94
|
+
* plain segments until selected. An explicit value always wins.
|
|
95
|
+
* @default "tertiary" (or "secondary" when `group` is true)
|
|
96
|
+
* @group Appearance
|
|
97
|
+
*/
|
|
98
|
+
emphasis?: ChoiceEmphasis;
|
|
99
|
+
disabled?: boolean;
|
|
100
|
+
/** Card appearance only: visually hide the radio/checkbox indicator (the real
|
|
101
|
+
* input is kept for selection + a11y; selection reads from the accent ring). */
|
|
102
|
+
hideIndicator?: boolean;
|
|
103
|
+
/**
|
|
104
|
+
* Wrap the items in a `Group` so they read as a single, merged control
|
|
105
|
+
* (shared dividers + flush outline). Best with `appearance="button"`.
|
|
106
|
+
*/
|
|
107
|
+
group?: boolean;
|
|
108
|
+
/** Root container background. Defaults to `transparent`. */
|
|
109
|
+
background?: PanelBackground;
|
|
110
|
+
/** Root container border. Defaults to `none`. */
|
|
111
|
+
border?: PanelBorder;
|
|
112
|
+
/** Root container corner radius. Defaults to `none`. */
|
|
113
|
+
radius?: PanelRadius;
|
|
114
|
+
/** Root container padding. Defaults to `none`. */
|
|
115
|
+
padding?: PanelPadding;
|
|
116
|
+
/** Root container shadow. Defaults to `none`. */
|
|
117
|
+
shadow?: PanelShadow;
|
|
118
|
+
passThrough?: ChoicePassThrough<RootElementAttributes>;
|
|
119
|
+
}
|
|
120
|
+
interface ConnectChoiceOptions extends ChoiceBaseProps<object> {
|
|
121
|
+
/** Radio group `name` shared across items (native single-select grouping). */
|
|
122
|
+
name?: string;
|
|
123
|
+
/** Currently-selected values (drives each control's `checked`). */
|
|
124
|
+
selectedValues?: ChoiceValue[];
|
|
125
|
+
/** Items-array mode input. */
|
|
126
|
+
items?: readonly ChoiceItemInput[];
|
|
127
|
+
class?: unknown;
|
|
128
|
+
[key: string]: unknown;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Spread onto the per-item `<Radio>`/`<Checkbox>`. `id` is always present so
|
|
132
|
+
* Astro's Radio (which requires `id`) type-checks against the spread; the index
|
|
133
|
+
* signature carries appearance/value/checked/feedback/etc. for either control.
|
|
134
|
+
*/
|
|
135
|
+
type ChoiceControlProps = {
|
|
136
|
+
id: string;
|
|
137
|
+
} & Record<string, unknown>;
|
|
138
|
+
/**
|
|
139
|
+
* Spread onto the label-less `<Radio>`/`<Checkbox>` indicator (card appearance).
|
|
140
|
+
* `id` is always present (Astro's Radio requires it); `as: "span"` makes the
|
|
141
|
+
* component render without its own `<label>` so it can live inside the
|
|
142
|
+
* Card-`<label>`'s Banner leading slot.
|
|
143
|
+
*/
|
|
144
|
+
type ChoiceIndicatorProps = {
|
|
145
|
+
id: string;
|
|
146
|
+
as: "span";
|
|
147
|
+
} & Record<string, unknown>;
|
|
148
|
+
interface ChoiceItemApi {
|
|
149
|
+
/** Stable id (equals `value`) — use as the `{#each}` key. */
|
|
150
|
+
id: string;
|
|
151
|
+
value: ChoiceValue;
|
|
152
|
+
label?: string;
|
|
153
|
+
/**
|
|
154
|
+
* Affix content for the wrapped Radio/Checkbox's `leading` slot (non-card).
|
|
155
|
+
* Framework render content — spread as content, not a `*Props` bag.
|
|
156
|
+
*/
|
|
157
|
+
leading?: unknown;
|
|
158
|
+
/** Affix content for the wrapped Radio/Checkbox's `trailing` slot. */
|
|
159
|
+
trailing?: unknown;
|
|
160
|
+
/** Spread onto the per-item `<Radio>`/`<Checkbox>` (non-card appearances). */
|
|
161
|
+
controlProps?: ChoiceControlProps;
|
|
162
|
+
/** Spread onto the inner `<Card>` (card appearance, rendered `as="label"`). */
|
|
163
|
+
cardProps?: Record<string, unknown>;
|
|
164
|
+
/** Spread onto the label-less indicator in the Card leading slot (card appearance). */
|
|
165
|
+
indicatorProps?: ChoiceIndicatorProps;
|
|
166
|
+
}
|
|
167
|
+
interface ChoiceRootProps {
|
|
168
|
+
class: string;
|
|
169
|
+
"data-component": "choice";
|
|
170
|
+
"data-choice-root": "";
|
|
171
|
+
"data-type": ChoiceType;
|
|
172
|
+
"data-appearance": ChoiceAppearance;
|
|
173
|
+
role: "radiogroup" | "group";
|
|
174
|
+
"aria-orientation": ChoiceOrientation;
|
|
175
|
+
[key: string]: unknown;
|
|
176
|
+
}
|
|
177
|
+
interface ChoiceApi {
|
|
178
|
+
rootProps: ChoiceRootProps;
|
|
179
|
+
/** Echoed so templates can branch Radio vs Checkbox uniformly across items. */
|
|
180
|
+
type: ChoiceType;
|
|
181
|
+
appearance: ChoiceAppearance;
|
|
182
|
+
items: ChoiceItemApi[];
|
|
183
|
+
/** True when items should be wrapped in a `<Group>`. */
|
|
184
|
+
group: boolean;
|
|
185
|
+
/** Spread onto the `<Group>` wrapper when `group` is true. */
|
|
186
|
+
groupProps?: Record<string, unknown>;
|
|
187
|
+
}
|
|
188
|
+
interface ConnectChoiceItemOptions {
|
|
189
|
+
type?: ChoiceType;
|
|
190
|
+
appearance?: ChoiceAppearance;
|
|
191
|
+
value: ChoiceValue;
|
|
192
|
+
label?: string;
|
|
193
|
+
selected?: boolean;
|
|
194
|
+
disabled?: boolean;
|
|
195
|
+
name?: string;
|
|
196
|
+
emphasis?: ChoiceEmphasis;
|
|
197
|
+
feedback?: ChoiceFeedback;
|
|
198
|
+
fullWidth?: boolean;
|
|
199
|
+
size?: ChoiceSize;
|
|
200
|
+
header?: unknown;
|
|
201
|
+
footer?: unknown;
|
|
202
|
+
/** Affix render content (forwarded by the template, stripped from the bag). */
|
|
203
|
+
leading?: unknown;
|
|
204
|
+
/** Affix render content (forwarded by the template, stripped from the bag). */
|
|
205
|
+
trailing?: unknown;
|
|
206
|
+
id?: string | null;
|
|
207
|
+
/**
|
|
208
|
+
* Whether this item is part of a merged `group`. Only shifts the emphasis
|
|
209
|
+
* default (grouped → `"secondary"`, standalone → `"tertiary"`); an explicit
|
|
210
|
+
* `emphasis` always wins.
|
|
211
|
+
*/
|
|
212
|
+
group?: boolean;
|
|
213
|
+
hideIndicator?: boolean;
|
|
214
|
+
passThrough?: ChoicePassThrough;
|
|
215
|
+
[key: string]: unknown;
|
|
216
|
+
}
|
|
217
|
+
interface ChoiceItemControlApi {
|
|
218
|
+
type: ChoiceType;
|
|
219
|
+
appearance: ChoiceAppearance;
|
|
220
|
+
/** Non-card appearances. */
|
|
221
|
+
controlProps?: ChoiceControlProps;
|
|
222
|
+
/** Card appearance — the `<Card as="label">` bag. */
|
|
223
|
+
cardProps?: Record<string, unknown>;
|
|
224
|
+
/** Card appearance — the label-less indicator bag. */
|
|
225
|
+
indicatorProps?: ChoiceIndicatorProps;
|
|
226
|
+
}
|
|
227
|
+
//#endregion
|
|
228
|
+
export { ChoiceApi, ChoiceAppearance, ChoiceBaseProps, ChoiceConfig, ChoiceControlProps, ChoiceEmphasis, ChoiceFeedback, ChoiceIndicatorProps, ChoiceItemApi, ChoiceItemControlApi, ChoiceItemInput, ChoiceOrientation, ChoicePassThrough, ChoiceRootProps, ChoiceSize, ChoiceType, ChoiceValue, ConnectChoiceItemOptions, ConnectChoiceOptions, ElementAttributes, HeadlessChoice };
|
|
229
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","names":[],"sources":["../../src/types.ts"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@pindoba/core-choice",
|
|
3
|
+
"version": "0.0.0-alpha-20260617191010",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"sideEffects": false,
|
|
7
|
+
"main": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.js"
|
|
13
|
+
},
|
|
14
|
+
"./*": {
|
|
15
|
+
"types": "./dist/src/*.d.ts",
|
|
16
|
+
"import": "./dist/src/*.js"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"files": [
|
|
20
|
+
"dist"
|
|
21
|
+
],
|
|
22
|
+
"dependencies": {
|
|
23
|
+
"nanostores": "^1.3.0",
|
|
24
|
+
"@pindoba/normalize-props": "0.0.0-alpha-20260617191010",
|
|
25
|
+
"@pindoba/styled-system": "0.0.0-alpha-20260617191010",
|
|
26
|
+
"@pindoba/styles-choice": "0.0.0-alpha-20260617191010",
|
|
27
|
+
"@pindoba/core-panel": "0.0.0-alpha-20260617191010"
|
|
28
|
+
},
|
|
29
|
+
"devDependencies": {
|
|
30
|
+
"tsdown": "^0.22.2",
|
|
31
|
+
"typescript": "^6.0.3"
|
|
32
|
+
},
|
|
33
|
+
"scripts": {
|
|
34
|
+
"build": "tsdown",
|
|
35
|
+
"dev": "tsdown --watch",
|
|
36
|
+
"clean": "rm -rf dist && rm -rf node_modules && rm -rf .turbo"
|
|
37
|
+
}
|
|
38
|
+
}
|