@pinfold/core 0.0.0-stage → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,3 +1,42 @@
1
- # Temporary Holding Version
1
+ # @pinfold/core
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ The framework-free layer of [Pinfold](../../README.md): each component's behaviour rules, the
4
+ helpers, keyboard rules, component metadata and the OKLCH palette engine that every Pinfold
5
+ adapter shares. No React,
6
+ no dependencies. A test fails the build if a framework import ever appears here.
7
+
8
+ Most apps never install this directly. `@pinfold/react` depends on it.
9
+
10
+ ## Exports
11
+
12
+ | | |
13
+ | --- | --- |
14
+ | `cn`, `mergeProps`, `composeRefs` | class joining and prop merging (handlers chain, styles merge) |
15
+ | `variants` | `cva`-style class resolution |
16
+ | `nextIndexFromKey` | the WAI-ARIA roving-focus key map (orientation, RTL, loop) |
17
+ | `dimensionVars` | `dimensions` config → `--pinfold-<component>-*` custom properties |
18
+ | `resolveNode`, `dataAttr`, `ariaAttr` | slot value and attribute helpers |
19
+ | `warnOnce`, `__DEV__` | dev-only diagnostics, stripped in production |
20
+ | `setAccordionItem`, `openAllAccordion`, `accordionFocusTarget`, … | the accordion's rules as pure functions |
21
+
22
+ ## Metadata
23
+
24
+ `@pinfold/core/meta`: `accordionMeta` (every option, default, slot, keyboard key and ARIA rule),
25
+ `validateConfig`, `toJsonSchema` and `metaToMarkdown`. Docs, the playground, the CLI, the MCP
26
+ server and dev validation are all generated from it. Apps never ship it.
27
+
28
+ ## Palette
29
+
30
+ ```js
31
+ import { createTheme, contrastRatio, toDTCG } from '@pinfold/core/palette';
32
+
33
+ const theme = createTheme({ primary: 'emerald', accent: 'amber', radius: 'lg' });
34
+ theme.vars; // { '--pinfold-primary-500': '#009b60', … }
35
+ theme.css; // the stylesheet `npx pinfold theme` writes
36
+ theme.contrast; // WCAG report per role and step
37
+ toDTCG(theme); // W3C design tokens
38
+ ```
39
+
40
+ Seven roles × eleven OKLCH steps, gamut-mapped, with sRGB hex fallbacks.
41
+
42
+ MIT © Indranil Bhattacharya
package/dist/index.cjs ADDED
@@ -0,0 +1,242 @@
1
+ 'use strict';
2
+
3
+ // src/utils.ts
4
+ function cn(...parts) {
5
+ let out = "";
6
+ for (let i = 0; i < parts.length; i++) {
7
+ const p = parts[i];
8
+ if (p) out = out ? out + " " + p : p;
9
+ }
10
+ return out;
11
+ }
12
+ function resolveNode(value, state) {
13
+ return typeof value === "function" ? value(state) : value;
14
+ }
15
+ function dataAttr(condition) {
16
+ return condition ? "" : void 0;
17
+ }
18
+ function ariaAttr(condition) {
19
+ return condition ? "true" : void 0;
20
+ }
21
+ function composeRefs(...refs) {
22
+ return (node) => {
23
+ for (let i = 0; i < refs.length; i++) {
24
+ const ref = refs[i];
25
+ if (typeof ref === "function") ref(node);
26
+ else if (ref) ref.current = node;
27
+ }
28
+ };
29
+ }
30
+ var isHandler = (key) => key.length > 2 && key.charCodeAt(0) === 111 && key.charCodeAt(1) === 110;
31
+ function mergeProps(base, overrides) {
32
+ if (!overrides) return base;
33
+ const out = { ...base };
34
+ for (const key in overrides) {
35
+ const ours = base[key];
36
+ const theirs = overrides[key];
37
+ if (isHandler(key) && typeof ours === "function" && typeof theirs === "function") {
38
+ out[key] = (...args) => {
39
+ ours(...args);
40
+ const ev = args[0];
41
+ if (ev && ev.defaultPrevented) return;
42
+ theirs(...args);
43
+ };
44
+ } else if (key === "className") {
45
+ out[key] = cn(ours, theirs);
46
+ } else if (key === "style") {
47
+ out[key] = { ...ours, ...theirs };
48
+ } else if (key === "ref") {
49
+ out[key] = composeRefs(ours, theirs);
50
+ } else {
51
+ out[key] = theirs;
52
+ }
53
+ }
54
+ return out;
55
+ }
56
+
57
+ // src/variants.ts
58
+ function variants(config) {
59
+ const { base = "", variants: map, defaultVariants = {} } = config;
60
+ return function resolve(props) {
61
+ var _a;
62
+ let out = base;
63
+ for (const key in map) {
64
+ const chosen = (_a = props == null ? void 0 : props[key]) != null ? _a : defaultVariants[key];
65
+ if (chosen == null) continue;
66
+ const cls = map[key][chosen];
67
+ if (cls) out = cn(out, cls);
68
+ }
69
+ return cn(out, props == null ? void 0 : props.className);
70
+ };
71
+ }
72
+
73
+ // src/navigation.ts
74
+ function nextIndexFromKey(key, current, count, { orientation = "vertical", dir = "ltr", loop = true } = {}) {
75
+ if (count === 0) return null;
76
+ const forward = orientation === "vertical" ? "ArrowDown" : dir === "rtl" ? "ArrowLeft" : "ArrowRight";
77
+ const backward = orientation === "vertical" ? "ArrowUp" : dir === "rtl" ? "ArrowRight" : "ArrowLeft";
78
+ switch (key) {
79
+ case forward: {
80
+ const next = current + 1;
81
+ return next < count ? next : loop ? 0 : current;
82
+ }
83
+ case backward: {
84
+ const prev = current - 1;
85
+ return prev >= 0 ? prev : loop ? count - 1 : current;
86
+ }
87
+ case "Home":
88
+ return 0;
89
+ case "End":
90
+ return count - 1;
91
+ default:
92
+ return null;
93
+ }
94
+ }
95
+
96
+ // src/dimensions.ts
97
+ function dimensionVars(component, dimensions) {
98
+ if (!dimensions) return void 0;
99
+ const out = {};
100
+ for (const [key, raw] of Object.entries(dimensions)) {
101
+ const value = raw;
102
+ if (value === void 0 || value === null || value === "") continue;
103
+ out[`--pinfold-${component}-${kebab(key)}`] = typeof value === "number" ? `${value}px` : value;
104
+ }
105
+ return out;
106
+ }
107
+ var kebab = (s) => s.replace(/[A-Z]/g, (m) => "-" + m.toLowerCase());
108
+
109
+ // src/accordion.logic.ts
110
+ function accordionRowId(item, index) {
111
+ var _a;
112
+ return (_a = item.id) != null ? _a : String(index);
113
+ }
114
+ function accordionPartIds(baseId, rowId) {
115
+ return { triggerId: `${baseId}-trigger-${rowId}`, panelId: `${baseId}-panel-${rowId}` };
116
+ }
117
+ function normalizeAccordionValue(value, mode) {
118
+ return mode === "single" ? value.slice(0, 1) : value.slice();
119
+ }
120
+ function initialAccordionValue(items, defaultValue, mode) {
121
+ if (defaultValue) return normalizeAccordionValue(defaultValue, mode);
122
+ const open = [];
123
+ items.forEach((item, i) => {
124
+ if (item.defaultOpen) open.push(accordionRowId(item, i));
125
+ });
126
+ return normalizeAccordionValue(open, mode);
127
+ }
128
+ function setAccordionItem(value, rows, id, open, rules) {
129
+ const row = rows.find((r) => r.id === id);
130
+ if (!row || row.disabled || rules.disabled) return null;
131
+ const isOpen = value.indexOf(id) !== -1;
132
+ if (isOpen === open) return null;
133
+ if (!open && !rules.collapsible && value.length === 1) return null;
134
+ if (open) return rules.mode === "single" ? [id] : value.concat(id);
135
+ return value.filter((v) => v !== id);
136
+ }
137
+ function openAllAccordion(value, rows, rules) {
138
+ if (rules.mode === "single" || rules.disabled) return null;
139
+ const next = rows.filter((r) => !r.disabled || value.indexOf(r.id) !== -1).map((r) => r.id);
140
+ return sameSet(value, next) ? null : next;
141
+ }
142
+ function closeAllAccordion(value, rows, rules) {
143
+ if (rules.disabled || !rules.collapsible) return null;
144
+ const locked = new Set(rows.filter((r) => r.disabled).map((r) => r.id));
145
+ const next = value.filter((id) => locked.has(id));
146
+ return sameSet(value, next) ? null : next;
147
+ }
148
+ function accordionFocusTarget(key, index, count, options = {}) {
149
+ return nextIndexFromKey(key, index, count, options);
150
+ }
151
+ function mapAccordionFields(records, fields) {
152
+ if (!fields) return records;
153
+ return records.map((record) => {
154
+ const out = { ...record };
155
+ for (const key in fields) {
156
+ const source = fields[key];
157
+ if (source && record != null && source in record) {
158
+ const v = record[source];
159
+ out[key] = key === "id" && v != null ? String(v) : v;
160
+ }
161
+ }
162
+ return out;
163
+ });
164
+ }
165
+ var ZERO = /^0*\.?0*(px|rem|em|%|vh|vw)?$/;
166
+ function accordionRowsJoined(variant = "solid", gap) {
167
+ if (gap === void 0 || gap === null || gap === "") return variant !== "separated" && variant !== "filled";
168
+ if (gap === "none" || gap === 0) return true;
169
+ return typeof gap === "string" && ZERO.test(gap.trim());
170
+ }
171
+ function inactiveAccordionOptions(input) {
172
+ var _a;
173
+ const variant = (_a = input.variant) != null ? _a : "solid";
174
+ const joined = accordionRowsJoined(variant, input.gap);
175
+ const card = variant === "solid" || variant === "outline";
176
+ const rows = variant === "separated" || variant === "filled";
177
+ const out = {};
178
+ if (variant === "ghost") {
179
+ out.radius = "Ghost has no surface to round. Pick solid or outline for a rounded container.";
180
+ out.itemRadius = "Ghost rows have no surface to round. Pick separated or filled for rounded rows.";
181
+ }
182
+ if (card) out.itemRadius = "In a solid or outline card the rows are not surfaces; the card takes `radius`.";
183
+ if (rows && joined) out.itemRadius = "With no gap the rows join into one group, rounded by `radius`.";
184
+ if (rows && !joined && input.itemRadius !== void 0) {
185
+ out.radius = 'Separated and filled rows are the surfaces and `itemRadius` already rounds them. Unset `itemRadius` so `radius` reaches the rows, or set `gap: "none"` to join them.';
186
+ }
187
+ if (rows && !joined) out.dividers = 'The rows are already apart. Dividers appear when `gap` is "none".';
188
+ if (input.indicator === "none") {
189
+ out.indicatorPosition = 'There is no indicator (`indicator: "none"`).';
190
+ out.animateIndicator = 'There is no indicator (`indicator: "none"`).';
191
+ }
192
+ if (input.disabled) out.disabledIds = "Every row is already disabled (`disabled: true`).";
193
+ return out;
194
+ }
195
+ function shouldMountPanel(policy, open, everOpened) {
196
+ if (policy === "always" || open) return true;
197
+ return policy === "first-open" && everOpened;
198
+ }
199
+ function sameSet(a, b) {
200
+ return a.length === b.length && a.every((v) => b.indexOf(v) !== -1);
201
+ }
202
+
203
+ // src/dev.ts
204
+ var __DEV__ = typeof process !== "undefined" && !!process.env && process.env.NODE_ENV !== "production";
205
+ var seen = /* @__PURE__ */ new Set();
206
+ function warnOnce(condition, message) {
207
+ if (!__DEV__ || !condition || seen.has(message)) return;
208
+ seen.add(message);
209
+ console.warn(`[pinfold] ${message}`);
210
+ }
211
+ function resetWarnings() {
212
+ seen.clear();
213
+ }
214
+
215
+ // src/index.ts
216
+ var version = "0.2.0";
217
+
218
+ exports.__DEV__ = __DEV__;
219
+ exports.accordionFocusTarget = accordionFocusTarget;
220
+ exports.accordionPartIds = accordionPartIds;
221
+ exports.accordionRowId = accordionRowId;
222
+ exports.accordionRowsJoined = accordionRowsJoined;
223
+ exports.ariaAttr = ariaAttr;
224
+ exports.closeAllAccordion = closeAllAccordion;
225
+ exports.cn = cn;
226
+ exports.composeRefs = composeRefs;
227
+ exports.dataAttr = dataAttr;
228
+ exports.dimensionVars = dimensionVars;
229
+ exports.inactiveAccordionOptions = inactiveAccordionOptions;
230
+ exports.initialAccordionValue = initialAccordionValue;
231
+ exports.mapAccordionFields = mapAccordionFields;
232
+ exports.mergeProps = mergeProps;
233
+ exports.nextIndexFromKey = nextIndexFromKey;
234
+ exports.normalizeAccordionValue = normalizeAccordionValue;
235
+ exports.openAllAccordion = openAllAccordion;
236
+ exports.resetWarnings = resetWarnings;
237
+ exports.resolveNode = resolveNode;
238
+ exports.setAccordionItem = setAccordionItem;
239
+ exports.shouldMountPanel = shouldMountPanel;
240
+ exports.variants = variants;
241
+ exports.version = version;
242
+ exports.warnOnce = warnOnce;
@@ -0,0 +1,211 @@
1
+ /** Shared scale used by every Pinfold component. */
2
+ type PinfoldSize = 'sm' | 'md' | 'lg';
3
+ type PinfoldRadius = 'none' | 'sm' | 'md' | 'lg' | 'full';
4
+ type PinfoldTone = 'neutral' | 'primary' | 'success' | 'warning' | 'danger' | 'info';
5
+ type PinfoldOrientation = 'horizontal' | 'vertical';
6
+ type PinfoldDir = 'ltr' | 'rtl';
7
+ type PinfoldTheme = 'light' | 'dark' | 'system';
8
+ /** When a component's code loads. `auto`: light components eagerly, heavy ones when visible. */
9
+ type PinfoldLazy = 'auto' | 'eager' | 'visible' | 'idle';
10
+ /** Visual style pack, applied through `data-pinfold-style`. */
11
+ type PinfoldStylePack = 'default' | 'glass' | 'material' | 'noise' | 'brutalist';
12
+ /** Any DOM props bag a component hands back from a `getXProps()` call. */
13
+ type PropsBag = Record<string, any>;
14
+ /** A CSS length. Numbers are px, strings pass through (`'50%'`, `'12rem'`, `calc()`). */
15
+ type Length = number | string;
16
+ /** A callback ref or a `{ current }` object, the two shapes every framework's refs reduce to. */
17
+ type Ref<T> = ((node: T | null) => void) | {
18
+ current: T | null;
19
+ } | null;
20
+
21
+ /** Join truthy class names. Deliberately tiny — no `clsx` dependency. */
22
+ declare function cn(...parts: Array<string | false | null | undefined>): string;
23
+ /**
24
+ * A slot value that may be static or derived from live state.
25
+ *
26
+ * Every renderable field in a Pinfold config accepts both, so a caret can react to
27
+ * `open` without the consumer dropping down to a full slot override.
28
+ */
29
+ type Slottable<State, T = unknown> = T | ((state: State) => T);
30
+ /** Resolve a `Slottable` against the current state. */
31
+ declare function resolveNode<State, T>(value: Slottable<State, T> | undefined, state: State): T | undefined;
32
+ /** `data-*` attributes render when true and vanish when false. */
33
+ declare function dataAttr(condition: unknown): '' | undefined;
34
+ /** `aria-*` attributes want the literal strings. */
35
+ declare function ariaAttr(condition: unknown): 'true' | undefined;
36
+ declare function composeRefs<T>(...refs: Array<Ref<T> | undefined>): (node: T | null) => void;
37
+ /**
38
+ * Merge a user props bag over ours: event handlers chain (ours first, then
39
+ * theirs, unless ours called `preventDefault`), `className` concatenates,
40
+ * `style` shallow-merges, everything else overrides.
41
+ */
42
+ declare function mergeProps(base: PropsBag, overrides?: PropsBag): PropsBag;
43
+
44
+ type VariantShape = Record<string, Record<string, string>>;
45
+ type VariantProps<V extends VariantShape> = {
46
+ [K in keyof V]?: keyof V[K] | null | undefined;
47
+ };
48
+ /**
49
+ * 20-line class-variance resolver. Same ergonomics as `cva` without the
50
+ * dependency or its runtime — components are static strings plus a lookup.
51
+ */
52
+ declare function variants<V extends VariantShape>(config: {
53
+ base?: string;
54
+ variants: V;
55
+ defaultVariants?: VariantProps<V>;
56
+ }): (props?: VariantProps<V> & {
57
+ className?: string;
58
+ }) => string;
59
+
60
+ interface ListNavOptions {
61
+ orientation?: PinfoldOrientation;
62
+ dir?: PinfoldDir;
63
+ /** Wrap from last to first. Default true. */
64
+ loop?: boolean;
65
+ }
66
+ /**
67
+ * WAI-ARIA roving-focus key resolution, shared by every list-like component
68
+ * (accordion, tabs, menu, listbox, toolbar…).
69
+ *
70
+ * Returns the index to move focus to, or `null` when the key is not ours —
71
+ * callers must not `preventDefault()` on `null`.
72
+ */
73
+ declare function nextIndexFromKey(key: string, current: number, count: number, { orientation, dir, loop }?: ListNavOptions): number | null;
74
+
75
+ /**
76
+ * Turn a `dimensions` config object into CSS custom properties on the root.
77
+ *
78
+ * dimensionVars('accordion', { paddingX: 24, panelMaxHeight: '18rem' })
79
+ * // → { '--pinfold-accordion-padding-x': '24px', '--pinfold-accordion-panel-max-height': '18rem' }
80
+ *
81
+ * Numbers become px; strings pass through untouched, so `'50%'`, `'12rem'`,
82
+ * `'clamp(...)'` and `var(...)` all work. Every component's CSS reads these
83
+ * with a fallback, which is why one shared resolver covers all of them.
84
+ */
85
+ declare function dimensionVars<D extends object>(component: string, dimensions: D | undefined): Record<string, string> | undefined;
86
+
87
+ /**
88
+ * Accordion rules as pure functions. No DOM, no framework: every adapter
89
+ * (React today) calls these and only wires the results to its own state and
90
+ * events, so behaviour can never drift between adapters.
91
+ */
92
+ type AccordionMode = 'single' | 'multiple';
93
+ /** Why the open set changed. Passed to `onBeforeChange` and `onValueChange`. */
94
+ type AccordionChangeReason = 'click' | 'keyboard' | 'api' | 'find-in-page' | 'hash';
95
+ interface AccordionChangeDetails<E = unknown> {
96
+ /** The row that triggered the change. Absent for `openAll` / `closeAll`. */
97
+ id?: string;
98
+ open: boolean;
99
+ reason: AccordionChangeReason;
100
+ event?: E;
101
+ }
102
+ /** The minimum a row needs for the rules: its id and whether it is disabled. */
103
+ interface AccordionRowLike {
104
+ id: string;
105
+ disabled?: boolean;
106
+ }
107
+ interface AccordionRules {
108
+ mode: AccordionMode;
109
+ collapsible: boolean;
110
+ /** Disables every row. */
111
+ disabled?: boolean;
112
+ }
113
+ /** Row id: the configured `id`, else the index as a string. */
114
+ declare function accordionRowId(item: {
115
+ id?: string;
116
+ }, index: number): string;
117
+ /** Trigger and panel ids for a row, derived from the instance's base id. */
118
+ declare function accordionPartIds(baseId: string, rowId: string): {
119
+ triggerId: string;
120
+ panelId: string;
121
+ };
122
+ /** Single mode keeps at most one open id. */
123
+ declare function normalizeAccordionValue(value: readonly string[], mode: AccordionMode): string[];
124
+ /** The first open set: `defaultValue` when given, else every row with `defaultOpen`. */
125
+ declare function initialAccordionValue(items: ReadonlyArray<{
126
+ id?: string;
127
+ defaultOpen?: boolean;
128
+ }>, defaultValue: readonly string[] | undefined, mode: AccordionMode): string[];
129
+ /**
130
+ * The open set after asking row `id` to become `open`, or `null` when the
131
+ * rules refuse (unknown or disabled row, no change, or closing the last open
132
+ * row of a non-collapsible accordion, in either mode).
133
+ */
134
+ declare function setAccordionItem(value: readonly string[], rows: readonly AccordionRowLike[], id: string, open: boolean, rules: AccordionRules): string[] | null;
135
+ /** `openAll`: every enabled row, multiple mode only. */
136
+ declare function openAllAccordion(value: readonly string[], rows: readonly AccordionRowLike[], rules: AccordionRules): string[] | null;
137
+ /** `closeAll`: refused for a non-collapsible accordion. Disabled rows keep their state. */
138
+ declare function closeAllAccordion(value: readonly string[], rows: readonly AccordionRowLike[], rules: AccordionRules): string[] | null;
139
+ interface AccordionKeyOptions {
140
+ orientation?: PinfoldOrientation;
141
+ dir?: PinfoldDir;
142
+ loop?: boolean;
143
+ }
144
+ /**
145
+ * The header index to focus for a key, or `null` when the key is not ours.
146
+ * Disabled headers stay focusable (APG), so they are not skipped.
147
+ */
148
+ declare function accordionFocusTarget(key: string, index: number, count: number, options?: AccordionKeyOptions): number | null;
149
+ /**
150
+ * Field mapping: lets raw records (a CMS row, a DB result) feed the accordion
151
+ * without a `.map()`. `{ id: 'slug', title: 'question', content: 'answer' }`.
152
+ */
153
+ type AccordionFieldMap<Row = any> = Partial<Record<'id' | 'title' | 'content' | 'description' | 'icon' | 'endIcon' | 'badge' | 'disabled' | 'defaultOpen', Extract<keyof Row, string>>>;
154
+ declare function mapAccordionFields<T>(records: readonly any[], fields: AccordionFieldMap | undefined): T[];
155
+ /**
156
+ * The appearance cascade, as rules every adapter and the docs share:
157
+ * 1. The variant decides what is a surface: the container (solid, outline), each row
158
+ * (separated, filled) or nothing (ghost).
159
+ * 2. `radius` shapes the container; `itemRadius` defaults to it.
160
+ * 3. A zero gap joins the rows. Joined separated or filled rows become one group whose outer
161
+ * corners follow the container `radius`; `dividers` draws the lines inside it.
162
+ */
163
+ type AccordionVariantName = 'solid' | 'outline' | 'separated' | 'filled' | 'ghost';
164
+ interface AccordionAppearanceInput {
165
+ variant?: AccordionVariantName;
166
+ /** Resolved gap: `dimensions.gap` if set, else `gap`. */
167
+ gap?: unknown;
168
+ radius?: unknown;
169
+ itemRadius?: unknown;
170
+ dividers?: boolean;
171
+ indicator?: unknown;
172
+ disabled?: boolean;
173
+ }
174
+ /** Whether the rows touch. The card and ghost variants default to no gap; separated and filled to a small one. */
175
+ declare function accordionRowsJoined(variant?: AccordionVariantName, gap?: unknown): boolean;
176
+ /**
177
+ * Options that have no visible effect with the rest of the config, each with the reason and
178
+ * what to do instead. Playgrounds disable them; the dev build warns when one is set explicitly.
179
+ */
180
+ declare function inactiveAccordionOptions(input: AccordionAppearanceInput): Record<string, string>;
181
+ /** When panel content is mounted. */
182
+ type AccordionMountPanels = 'always' | 'open' | 'first-open';
183
+ /** Whether a panel's content should be in the DOM right now. */
184
+ declare function shouldMountPanel(policy: AccordionMountPanels, open: boolean, everOpened: boolean): boolean;
185
+
186
+ /**
187
+ * Development-only diagnostics.
188
+ *
189
+ * Config-driven APIs fail quietly: a duplicated `id` or a `value` array that
190
+ * silently switches a component from uncontrolled to controlled produces
191
+ * confusing behaviour rather than an error. These warnings turn that class of
192
+ * mistake into a message, and vanish entirely from production builds because
193
+ * bundlers fold the `NODE_ENV` check.
194
+ */
195
+ declare const __DEV__: boolean;
196
+ /** Warn at most once per distinct message, so a render loop cannot spam the console. */
197
+ declare function warnOnce(condition: unknown, message: string): void;
198
+ /** Test hook — lets a suite assert the same warning twice. */
199
+ declare function resetWarnings(): void;
200
+
201
+ /**
202
+ * @pinfold/core: framework-free building blocks. Nothing here imports React or
203
+ * any other UI framework (enforced by `framework-isolation.test.ts`), so a
204
+ * future adapter reuses exactly the same rules.
205
+ */
206
+
207
+ /** Package version, injected at publish time by the release script. */
208
+ declare const version = "0.2.0";
209
+
210
+ export { __DEV__, accordionFocusTarget, accordionPartIds, accordionRowId, accordionRowsJoined, ariaAttr, closeAllAccordion, cn, composeRefs, dataAttr, dimensionVars, inactiveAccordionOptions, initialAccordionValue, mapAccordionFields, mergeProps, nextIndexFromKey, normalizeAccordionValue, openAllAccordion, resetWarnings, resolveNode, setAccordionItem, shouldMountPanel, variants, version, warnOnce };
211
+ export type { AccordionAppearanceInput, AccordionChangeDetails, AccordionChangeReason, AccordionFieldMap, AccordionKeyOptions, AccordionMode, AccordionMountPanels, AccordionRowLike, AccordionRules, AccordionVariantName, Length, ListNavOptions, PinfoldDir, PinfoldLazy, PinfoldOrientation, PinfoldRadius, PinfoldSize, PinfoldStylePack, PinfoldTheme, PinfoldTone, PropsBag, Ref, Slottable, VariantProps };