@pikacss/core 0.0.61 → 0.0.62

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -37,7 +37,7 @@ declare module '@pikacss/core' {
37
37
  * createEngine({ plugins: [important()] })
38
38
  * ```
39
39
  */
40
- declare function important(): EnginePlugin;
40
+ declare function important(): EnginePlugin<void>;
41
41
  //#endregion
42
42
  //#region src/plugins/keyframes.d.ts
43
43
  /**
@@ -143,7 +143,7 @@ declare module '@pikacss/core' {
143
143
  * createEngine({ plugins: [keyframes()] })
144
144
  * ```
145
145
  */
146
- declare function keyframes(): EnginePlugin;
146
+ declare function keyframes(): EnginePlugin<void>;
147
147
  interface ResolvedKeyframesConfig {
148
148
  name: string;
149
149
  frames: KeyframesProgress | Nullish;
@@ -176,6 +176,26 @@ interface Diagnostic {
176
176
  }
177
177
  /** Callback used by a host to receive structured diagnostics. */
178
178
  type DiagnosticHandler = (diagnostic: Diagnostic) => void;
179
+ /**
180
+ * Host semantic metadata for one engine, supplied by the integration/bundler
181
+ * host and transported — never interpreted — by the platform-neutral core.
182
+ *
183
+ * @remarks
184
+ * The host (Vite adapter, Nuxt module, a programmatic caller) is the
185
+ * authority for these values. Plugins consume them through
186
+ * `context.host` so project-relative resources resolve against the same
187
+ * effective PikaCSS project root as config discovery, scans, and generated
188
+ * artifacts — never against `process.cwd()` once a host supplied a more
189
+ * specific root (#118). Core adds no filesystem, path, or bundler APIs here.
190
+ */
191
+ interface EngineHostContext {
192
+ /**
193
+ * The effective PikaCSS project root for this engine (e.g. Vite's
194
+ * `config.root`, Nuxt's `rootDir`). Absent for standalone `createEngine()`
195
+ * callers that supply no host context.
196
+ */
197
+ projectRoot?: string;
198
+ }
179
199
  /** Runtime-only options accepted by {@link createEngine}. */
180
200
  interface CreateEngineOptions {
181
201
  /**
@@ -184,11 +204,40 @@ interface CreateEngineOptions {
184
204
  * @default A no-op handler.
185
205
  */
186
206
  onDiagnostic?: DiagnosticHandler;
207
+ /**
208
+ * Host semantic metadata for this engine (e.g. the effective project
209
+ * root). Exposed to plugins as `context.host`.
210
+ *
211
+ * @default An empty context.
212
+ */
213
+ host?: EngineHostContext;
187
214
  }
188
- /** Context passed to plugin hooks by the engine. */
189
- interface EnginePluginContext {
215
+ /**
216
+ * Context passed to plugin hooks by the engine.
217
+ *
218
+ * @remarks
219
+ * One context object exists per plugin definition **per engine** (#116): the
220
+ * same object is passed to every hook invocation of that plugin/engine pair,
221
+ * from `configureRawConfig` through committed notifications. Long-lived
222
+ * callbacks a plugin registers (shortcut resolvers, preflight functions,
223
+ * engine service methods) should close over this context — never over mutable
224
+ * plugin-factory closure variables, which are shared across every engine
225
+ * reusing the definition.
226
+ */
227
+ interface EnginePluginContext<State = void> {
190
228
  /** Instance-scoped diagnostic handler. */
191
229
  onDiagnostic: DiagnosticHandler;
230
+ /**
231
+ * Engine-local plugin state, created once per plugin/engine pair by the
232
+ * plugin's `createState()` initializer. `undefined` (typed `void`) for
233
+ * stateless plugins that omit the initializer.
234
+ */
235
+ state: State;
236
+ /**
237
+ * Host semantic metadata for this engine (#118). Read-only from a
238
+ * plugin's perspective; empty when no host context was supplied.
239
+ */
240
+ host: EngineHostContext;
192
241
  }
193
242
  //#endregion
194
243
  //#region src/resolver.d.ts
@@ -514,7 +563,7 @@ declare module '@pikacss/core' {
514
563
  * createEngine({ plugins: [selectors()] })
515
564
  * ```
516
565
  */
517
- declare function selectors$1(): EnginePlugin;
566
+ declare function selectors$1(): EnginePlugin<void>;
518
567
  declare class SelectorResolver extends RecursiveResolver<string> {}
519
568
  /**
520
569
  * Normalizes a `Selector` configuration into a `ResolvedRuleConfig`, a redirect string, or `undefined`.
@@ -598,7 +647,7 @@ declare module '@pikacss/core' {
598
647
  * createEngine({ plugins: [shortcuts()] })
599
648
  * ```
600
649
  */
601
- declare function shortcuts(): EnginePlugin;
650
+ declare function shortcuts(): EnginePlugin<void>;
602
651
  declare class ShortcutResolver extends RecursiveResolver<InternalStyleItem> {}
603
652
  //#endregion
604
653
  //#region src/plugins/variables.d.ts
@@ -749,7 +798,7 @@ declare module '@pikacss/core' {
749
798
  * createEngine({ plugins: [variables()] })
750
799
  * ```
751
800
  */
752
- declare function variables(): EnginePlugin;
801
+ declare function variables(): EnginePlugin<void>;
753
802
  interface ResolvedVariable {
754
803
  name: string;
755
804
  value: InternalPropertyValue;
@@ -1333,6 +1382,8 @@ type ExtractFn = (styleDefinition: InternalStyleDefinition) => Promise<Extracted
1333
1382
  *
1334
1383
  * @remarks Core plugins (`important`, `variables`, `keyframes`, `selectors`, `shortcuts`) are prepended automatically. The function resolves plugins, runs all configuration hooks in sequence, and returns the ready-to-use engine.
1335
1384
  *
1385
+ * The caller-owned `config` graph is treated as immutable input (#117): the engine clones it into an engine-local working copy before any plugin configuration hook runs, so plugin hooks that mutate their config (`config.layers ??= {}` and friends) never write back into caller-owned objects, and the same config object can be reused across sequential or concurrent `createEngine()` calls without accumulating setup mutations. Ordinary config data (plain objects/arrays, `Map`/`Set` contents, `Date`, `RegExp`) is recursively isolated — module-augmented plugin fields included; functions and other opaque class instances keep their identity and are treated as immutable values; the `plugins` array is copied while plugin definition objects keep their identity (#116).
1386
+ *
1336
1387
  * @example
1337
1388
  * ```ts
1338
1389
  * const engine = await createEngine({ prefix: 'pk-', plugins: [myPlugin()] })
@@ -1408,7 +1459,7 @@ declare class Engine {
1408
1459
  *
1409
1460
  * @param path - The file path (ideally absolute) the current config was derived from.
1410
1461
  *
1411
- * @remarks Call from a plugin (typically in `configureEngine`) after loading data from disk. Integration layers watch registered paths and rebuild the engine when any of them changes.
1462
+ * @remarks Call from a plugin after loading data from disk — typically in `configureEngine`, but registering during later hooks (e.g. while resolving inside `engine.use()`) is fully supported: each genuinely new path fires the `configDependencyAdded` committed notification so integration layers can extend an already-running watcher (#122). Integration layers watch registered paths and rebuild the engine when any of them changes.
1412
1463
  *
1413
1464
  * @example
1414
1465
  * ```ts
@@ -1433,7 +1484,7 @@ declare class Engine {
1433
1484
  *
1434
1485
  * @param atomicStyle - The atomic style that was just added to the store.
1435
1486
  *
1436
- * @remarks Called automatically by `use()` when a previously unseen atomic style is resolved.
1487
+ * @remarks Called automatically by `commitUse()` when a previously unseen atomic style is registered. This is a committed notification: the style's ID, cache keys, and store indices are already established, so mutating the payload is unsupported — plugins that need to transform styles must use the provisional hooks (`transformStyleItems`, `transformStyleDefinitions`, `transformSelectors`, `transformStyleContents`) instead (#114).
1437
1488
  *
1438
1489
  * @example
1439
1490
  * ```ts
@@ -1492,13 +1543,55 @@ declare class Engine {
1492
1543
  * ```
1493
1544
  */
1494
1545
  addPreflight(preflight: Preflight): void;
1546
+ /**
1547
+ * Provisionally resolves style items into a commit-ready plan without touching committed engine state.
1548
+ *
1549
+ * @param itemList - Style items to process: string references (shortcuts) and/or style definition objects.
1550
+ * @returns A promise of the {@link StyleUsePlan} to pass to `commitUse()`.
1551
+ *
1552
+ * @remarks
1553
+ * Runs the full provisional pipeline: `transformStyleItems`, extraction
1554
+ * (`transformStyleDefinitions`/`transformSelectors`), normalization, and the
1555
+ * normalized-content seam `transformStyleContents`. It allocates no atomic
1556
+ * style IDs, mutates no `EngineStore` state, and fires no committed
1557
+ * notifications — a rejection anywhere leaves the engine exactly as it was.
1558
+ * Plans deliberately carry no IDs: reuse-vs-fresh decisions read live store
1559
+ * state and are only valid inside `commitUse()` (#114).
1560
+ *
1561
+ * @example
1562
+ * ```ts
1563
+ * const plan = await engine.prepareUse({ color: 'red' })
1564
+ * const ids = engine.commitUse(plan)
1565
+ * ```
1566
+ */
1567
+ prepareUse(...itemList: InternalStyleItem[]): Promise<StyleUsePlan>;
1568
+ /**
1569
+ * Commits a prepared plan: allocates/reuses atomic style IDs and registers new styles in the store.
1570
+ *
1571
+ * @param plan - A plan produced by `prepareUse()`.
1572
+ * @returns An array containing any unresolved string references first, followed by atomic style IDs in resolution order.
1573
+ *
1574
+ * @remarks
1575
+ * This is the short, mutation-critical section and MUST stay synchronous:
1576
+ * integration layers commit whole modules inside a revision/epoch-checked
1577
+ * synchronous block, so an `await` here would reopen the stale-commit race
1578
+ * (#114). `atomicStyleAdded` fires per newly registered style as a committed
1579
+ * notification; a throwing observer is reported through the diagnostic
1580
+ * context but never rolls back the already-committed registration.
1581
+ *
1582
+ * @example
1583
+ * ```ts
1584
+ * const ids = engine.commitUse(await engine.prepareUse({ color: 'red' }))
1585
+ * ```
1586
+ */
1587
+ commitUse(plan: StyleUsePlan): string[];
1495
1588
  /**
1496
1589
  * Processes style items through the plugin pipeline and registers the resulting atomic styles in the store.
1497
1590
  *
1498
1591
  * @param itemList - Style items to process: string references (shortcuts) and/or style definition objects.
1499
1592
  * @returns An array containing any unresolved string references first, followed by atomic style IDs in resolution order.
1500
1593
  *
1501
- * @remarks Runs `transformStyleItems` and `extractStyleDefinition` hooks, resolves each extracted content into an atomic style, deduplicates by base key, and fires `atomicStyleAdded` for new entries.
1594
+ * @remarks Equivalent to `commitUse(await prepareUse(...itemList))` the convenience path for direct consumers. Integration layers that need whole-module transactionality call the two phases separately (#114).
1502
1595
  *
1503
1596
  * @example
1504
1597
  * ```ts
@@ -1529,12 +1622,11 @@ declare class Engine {
1529
1622
  * Renders atomic styles into a CSS string, optionally filtered by ID and grouped by layer.
1530
1623
  *
1531
1624
  * @param isFormatted - Whether to produce human-readable CSS with newlines and indentation.
1532
- * @param options - Optional filtering: `atomicStyleIds` to render a subset, `isPreview` to use placeholder IDs.
1625
+ * @param options - Optional filtering: `atomicStyleIds` to render a subset.
1533
1626
  * @param options.atomicStyleIds - Specific atomic style IDs to render instead of the full store.
1534
- * @param options.isPreview - Whether to keep placeholder IDs instead of substituting real class names.
1535
1627
  * @returns The rendered atomic-style CSS.
1536
1628
  *
1537
- * @remarks Styles are sorted by rendering weight (selector specificity depth), grouped into configured `@layer` blocks, and rendered. When `isPreview` is true, atomic style IDs remain as placeholders for tooling previews.
1629
+ * @remarks Styles are sorted by rendering weight (selector specificity depth), grouped into configured `@layer` blocks, and rendered.
1538
1630
  *
1539
1631
  * @example
1540
1632
  * ```ts
@@ -1543,7 +1635,6 @@ declare class Engine {
1543
1635
  */
1544
1636
  renderAtomicStyles(isFormatted: boolean, options?: {
1545
1637
  atomicStyleIds?: string[];
1546
- isPreview?: boolean;
1547
1638
  }): Promise<string>;
1548
1639
  /**
1549
1640
  * Renders the CSS `@layer` order declaration for all configured layers.
@@ -1575,6 +1666,23 @@ declare class Engine {
1575
1666
  * ```
1576
1667
  */
1577
1668
  declare function sortLayerNames(layers: Record<string, number>): string[];
1669
+ /**
1670
+ * The provisional result of `engine.prepareUse()`: fully transformed, extracted,
1671
+ * and normalized style contents plus unresolved string references, ready to be
1672
+ * committed via `engine.commitUse()`.
1673
+ *
1674
+ * @remarks
1675
+ * A plan deliberately carries no atomic style IDs and no base-key resolutions:
1676
+ * reuse-vs-fresh-ID decisions read live `EngineStore` state and are only valid
1677
+ * at the moment `commitUse()` runs. Discarding an uncommitted plan has no
1678
+ * effect on the engine (#114).
1679
+ */
1680
+ interface StyleUsePlan {
1681
+ /** String references no plugin resolved; echoed back verbatim by `commitUse()`. */
1682
+ unknown: Set<string>;
1683
+ /** Deduplicated, normalized style contents in resolution order. */
1684
+ contents: StyleContent[];
1685
+ }
1578
1686
  //#endregion
1579
1687
  //#region src/plugin.d.ts
1580
1688
  type DefineHooks<Hooks extends Record<string, [type: 'sync' | 'async', payload: unknown, returnValue?: unknown]>> = Hooks;
@@ -1586,35 +1694,72 @@ type EngineHooksDefinition = DefineHooks<{
1586
1694
  transformSelectors: ['async', selectors: string[]];
1587
1695
  transformStyleItems: ['async', styleItems: ResolvedStyleItem[]];
1588
1696
  transformStyleDefinitions: ['async', styleDefinitions: ResolvedStyleDefinition[]];
1697
+ transformStyleContents: ['async', styleContents: StyleContent[]];
1589
1698
  preflightUpdated: ['sync', void];
1590
1699
  atomicStyleAdded: ['sync', AtomicStyle];
1591
1700
  autocompleteConfigUpdated: ['sync', void];
1701
+ configDependencyAdded: ['sync', path: string];
1592
1702
  }>;
1593
1703
  type HookParams<H extends [type: 'sync' | 'async', payload: any, returnValue?: any]> = H[1] extends void ? [] : [payload: H[1]];
1594
- type PluginHookParams<H extends [type: 'sync' | 'async', payload: any, returnValue?: any]> = H[1] extends void ? [context?: EnginePluginContext] : [payload: H[1], context?: EnginePluginContext];
1704
+ type PluginHookParams<H extends [type: 'sync' | 'async', payload: any, returnValue?: any], State = any> = H[1] extends void ? [context: EnginePluginContext<State>] : [payload: H[1], context: EnginePluginContext<State>];
1595
1705
  type HookReturnType<H extends [type: 'sync' | 'async', payload: any, returnValue?: any]> = H extends [any, any, infer R] ? H[0] extends 'async' ? Promise<R> : R : H[0] extends 'async' ? Promise<H[1]> : H[1];
1596
1706
  type EngineHooks = { [K in keyof EngineHooksDefinition]: (plugins: EnginePlugin[], ...params: HookParams<EngineHooksDefinition[K]>) => HookReturnType<EngineHooksDefinition[K]> };
1597
1707
  /**
1598
1708
  * Creates an engine-local hook dispatcher bound to one diagnostic context.
1599
1709
  *
1600
1710
  * @internal
1711
+ * @remarks
1712
+ * Each dispatcher instance owns one plugin-context store: every plugin
1713
+ * definition gets exactly one `EnginePluginContext` (with `state` initialized
1714
+ * lazily via `createState()`) per dispatcher — i.e. per engine, since
1715
+ * `createEngine` creates one dispatcher per engine (#116). The same plugin
1716
+ * definition used with another dispatcher/engine gets a distinct context and
1717
+ * distinct state.
1718
+ */
1719
+ declare function createEngineHooks(context: Pick<EnginePluginContext, 'onDiagnostic'> & Partial<Pick<EnginePluginContext, 'host'>>): EngineHooks;
1720
+ type EnginePluginHooksOptions<State = any> = { [K in keyof EngineHooksDefinition]?: EngineHooksDefinition[K][0] extends 'async' ? (...params: PluginHookParams<EngineHooksDefinition[K], State>) => Awaitable<EngineHooksDefinition[K][1] | void> : (...params: PluginHookParams<EngineHooksDefinition[K], State>) => EngineHooksDefinition[K][1] | void };
1721
+ /**
1722
+ * Describes an engine plugin that can hook into the PikaCSS engine lifecycle.
1723
+ *
1724
+ * @remarks
1725
+ * A plugin object is a reusable **definition**, not a single-engine resource
1726
+ * (#116): the same object may be passed to any number of `createEngine()`
1727
+ * calls, sequentially or concurrently. Mutable per-engine data therefore must
1728
+ * never live in the plugin factory's closure — declare it via `createState`
1729
+ * and read/write it through `context.state`, which the engine keeps isolated
1730
+ * per plugin/engine pair. Factory arguments that are never mutated may stay in
1731
+ * the closure as immutable definition configuration.
1601
1732
  */
1602
- declare function createEngineHooks(context: EnginePluginContext): EngineHooks;
1603
- type EnginePluginHooksOptions = { [K in keyof EngineHooksDefinition]?: EngineHooksDefinition[K][0] extends 'async' ? (...params: PluginHookParams<EngineHooksDefinition[K]>) => Awaitable<EngineHooksDefinition[K][1] | void> : (...params: PluginHookParams<EngineHooksDefinition[K]>) => EngineHooksDefinition[K][1] | void };
1604
- /** Describes an engine plugin that can hook into the PikaCSS engine lifecycle. */
1605
- interface EnginePlugin extends EnginePluginHooksOptions {
1733
+ interface EnginePlugin<State = any> extends EnginePluginHooksOptions<State> {
1606
1734
  /** The unique human-readable name identifying this plugin in diagnostics. */
1607
1735
  name: string;
1608
1736
  /** Controls execution order relative to other plugins. */
1609
1737
  order?: 'pre' | 'post';
1738
+ /**
1739
+ * Initializes this plugin's engine-local state.
1740
+ *
1741
+ * @returns The fresh state for one engine.
1742
+ *
1743
+ * @remarks
1744
+ * Invoked by the engine at most once per plugin definition **per engine**,
1745
+ * before the first hook of this plugin runs for that engine; every hook
1746
+ * invocation of that plugin/engine pair then receives the same object via
1747
+ * `context.state`. Another engine reusing the same definition gets a
1748
+ * distinct state object. Stateless plugins simply omit this.
1749
+ */
1750
+ createState?: () => State;
1610
1751
  }
1611
1752
  /**
1612
1753
  * Identity helper that provides type inference for an engine plugin definition.
1613
1754
  *
1614
1755
  * @param plugin - The plugin definition to return unchanged.
1615
1756
  * @returns The same plugin instance.
1757
+ *
1758
+ * @remarks
1759
+ * When the plugin declares `createState`, the state type is inferred from its
1760
+ * return value and every hook's `context.state` is typed accordingly.
1616
1761
  */
1617
- declare function defineEnginePlugin(plugin: EnginePlugin): EnginePlugin;
1762
+ declare function defineEnginePlugin<State = void>(plugin: EnginePlugin<State>): EnginePlugin<State>;
1618
1763
  //#endregion
1619
1764
  //#region src/generated/csstype.d.ts
1620
1765
  type UnionString$1 = string & {};
@@ -37494,4 +37639,4 @@ declare function renderCSSStyleBlocks(blocks: CSSStyleBlocks, isFormatted: boole
37494
37639
  */
37495
37640
  declare function defineEngineConfig<const T extends EngineConfig>(config: T): T;
37496
37641
  //#endregion
37497
- export { Arrayable, type AutocompleteConfig, type AutocompleteContribution, type AutocompletePatternsConfig, Awaitable, type CSSProperty, type CSSSelector, type CSSStyleBlockBody, type CSSStyleBlocks, type CreateEngineOptions, type DefineAutocomplete, type Diagnostic, type DiagnosticHandler, type DiagnosticLevel, type Engine, type EngineConfig, type EnginePlugin, type EnginePluginContext, FromKebab, GetValue, ImportantConfig, IsEqual, IsNever, Keyframes, KeyframesConfig, KeyframesProgress, Nullish, type PikaAugment, type Preflight, type PreflightDefinition, type PreflightFn, type Properties, type PropertyValue, ResolveFrom, type ResolvedLayerName, type ResolvedPreflight, Selector, SelectorsConfig, Shortcut, ShortcutsConfig, Simplify, type StyleDefinition, type StyleDefinitionMap, type StyleItem, ToKebab, UnionString, UnionToIntersection, Variable, VariableAutocomplete, VariableObject, VariablesConfig, VariablesDefinition, appendAutocomplete, createEngine, createLogger, defineEngineConfig, defineEnginePlugin, escapeRegExp, extractUsedVarNames, extractUsedVarNamesFromPreflightResult, important, isPlainObjectRecord, keyframes, log, normalizeVariableName, renderCSSStyleBlocks, resolveSelectorConfig, selectors$1 as selectors, shortcuts, sortLayerNames, variables };
37642
+ export { Arrayable, type AutocompleteConfig, type AutocompleteContribution, type AutocompletePatternsConfig, Awaitable, type CSSProperty, type CSSSelector, type CSSStyleBlockBody, type CSSStyleBlocks, type CreateEngineOptions, type DefineAutocomplete, type Diagnostic, type DiagnosticHandler, type DiagnosticLevel, type Engine, type EngineConfig, type EngineHostContext, type EnginePlugin, type EnginePluginContext, FromKebab, GetValue, ImportantConfig, IsEqual, IsNever, Keyframes, KeyframesConfig, KeyframesProgress, Nullish, type PikaAugment, type Preflight, type PreflightDefinition, type PreflightFn, type Properties, type PropertyValue, ResolveFrom, type ResolvedLayerName, type ResolvedPreflight, Selector, SelectorsConfig, Shortcut, ShortcutsConfig, Simplify, type StyleDefinition, type StyleDefinitionMap, type StyleItem, type StyleUsePlan, ToKebab, UnionString, UnionToIntersection, Variable, VariableAutocomplete, VariableObject, VariablesConfig, VariablesDefinition, appendAutocomplete, createEngine, createLogger, defineEngineConfig, defineEnginePlugin, escapeRegExp, extractUsedVarNames, extractUsedVarNamesFromPreflightResult, important, isPlainObjectRecord, keyframes, log, normalizeVariableName, renderCSSStyleBlocks, resolveSelectorConfig, selectors$1 as selectors, shortcuts, sortLayerNames, variables };
package/dist/index.mjs CHANGED
@@ -1873,6 +1873,93 @@ function getOrderSensitiveDependencyKeys(scoped, property) {
1873
1873
  return dependencyKeys;
1874
1874
  }
1875
1875
  //#endregion
1876
+ //#region src/config-clone.ts
1877
+ /**
1878
+ * Deep-copies ordinary config data while preserving behavioral identities.
1879
+ *
1880
+ * Recursively isolated (fresh copies): plain objects (null or Object
1881
+ * prototype, third-party augmented fields included), arrays, `Map` keys and
1882
+ * values, `Set` values, `Date`, `RegExp` (with `lastIndex`).
1883
+ *
1884
+ * Identity-preserved (returned as-is): primitives, functions/callbacks, and
1885
+ * any other non-plain instance (class instances, typed arrays, promises, …) —
1886
+ * Core cannot know a safe clone semantic for those, so they are treated as
1887
+ * opaque immutable values.
1888
+ *
1889
+ * Cycles and diamond references between plain objects/arrays/Maps/Sets are
1890
+ * preserved through `seen`; `Date`/`RegExp` diamonds become independent
1891
+ * value copies (they are immutable-by-convention config data).
1892
+ */
1893
+ function cloneConfigValue(value, seen) {
1894
+ if (typeof value !== "object" || value == null) return value;
1895
+ const cached = seen.get(value);
1896
+ if (cached != null) return cached;
1897
+ if (Array.isArray(value)) {
1898
+ const copy = [];
1899
+ seen.set(value, copy);
1900
+ for (const item of value) copy.push(cloneConfigValue(item, seen));
1901
+ return copy;
1902
+ }
1903
+ if (value instanceof Date) return new Date(value.getTime());
1904
+ if (value instanceof RegExp) {
1905
+ const copy = new RegExp(value.source, value.flags);
1906
+ copy.lastIndex = value.lastIndex;
1907
+ return copy;
1908
+ }
1909
+ if (value instanceof Map) {
1910
+ const copy = /* @__PURE__ */ new Map();
1911
+ seen.set(value, copy);
1912
+ for (const [key, entry] of value) copy.set(cloneConfigValue(key, seen), cloneConfigValue(entry, seen));
1913
+ return copy;
1914
+ }
1915
+ if (value instanceof Set) {
1916
+ const copy = /* @__PURE__ */ new Set();
1917
+ seen.set(value, copy);
1918
+ for (const item of value) copy.add(cloneConfigValue(item, seen));
1919
+ return copy;
1920
+ }
1921
+ const prototype = Object.getPrototypeOf(value);
1922
+ if (prototype !== Object.prototype && prototype !== null) return value;
1923
+ const copy = prototype === null ? Object.create(null) : {};
1924
+ seen.set(value, copy);
1925
+ for (const [key, entry] of Object.entries(value)) if (key === "__proto__") Object.defineProperty(copy, key, {
1926
+ value: cloneConfigValue(entry, seen),
1927
+ enumerable: true,
1928
+ writable: true,
1929
+ configurable: true
1930
+ });
1931
+ else copy[key] = cloneConfigValue(entry, seen);
1932
+ return copy;
1933
+ }
1934
+ /**
1935
+ * Creates the engine-local mutable working copy of a caller-owned config.
1936
+ * @internal
1937
+ *
1938
+ * @param config - The caller-owned engine configuration.
1939
+ * @returns An independent working config for one `createEngine()` invocation.
1940
+ *
1941
+ * @remarks
1942
+ * `createEngine(config)` treats the caller's `EngineConfig` graph as
1943
+ * immutable input (#117): plugin configuration hooks mutate this working
1944
+ * copy, never the caller's objects, so one caller config can be reused
1945
+ * across sequential or concurrent engine creations without accumulating
1946
+ * setup mutations. Ordinary config data is recursively isolated —
1947
+ * including module-augmented third-party fields; functions and opaque
1948
+ * class instances keep their identity; and the `plugins` array is copied
1949
+ * while the `EnginePlugin` definition objects inside it keep their
1950
+ * identity, per the #116 reusable-definition contract (per-engine plugin
1951
+ * state is keyed by definition identity).
1952
+ */
1953
+ function cloneEngineConfig(config) {
1954
+ const seen = /* @__PURE__ */ new WeakMap();
1955
+ const plugins = config.plugins;
1956
+ if (plugins != null) {
1957
+ seen.set(plugins, [...plugins]);
1958
+ for (const plugin of plugins) if (typeof plugin === "object" && plugin != null) seen.set(plugin, plugin);
1959
+ }
1960
+ return cloneConfigValue(config, seen);
1961
+ }
1962
+ //#endregion
1876
1963
  //#region src/constants.ts
1877
1964
  /**
1878
1965
  * CSS `@layer` at-rule prefix used when constructing layer-scoped selectors
@@ -2108,7 +2195,14 @@ function createExtractFn(options) {
2108
2195
  //#endregion
2109
2196
  //#region src/plugin.ts
2110
2197
  const VOID_HOOKS = new Set(["preflightUpdated", "autocompleteConfigUpdated"]);
2111
- const DEFAULT_PLUGIN_CONTEXT = { onDiagnostic: noopDiagnosticHandler };
2198
+ const DEFAULT_PLUGIN_CONTEXT = {
2199
+ onDiagnostic: noopDiagnosticHandler,
2200
+ state: void 0,
2201
+ host: {}
2202
+ };
2203
+ function resolvePluginContext(source, plugin) {
2204
+ return typeof source === "function" ? source(plugin) : source;
2205
+ }
2112
2206
  function getPluginHook(plugin, hook) {
2113
2207
  const hookFn = plugin[hook];
2114
2208
  return typeof hookFn === "function" ? hookFn : null;
@@ -2159,12 +2253,13 @@ async function execAsyncHook(plugins, hook, payload, context = DEFAULT_PLUGIN_CO
2159
2253
  for (const plugin of plugins) {
2160
2254
  const hookFn = getPluginHook(plugin, hook);
2161
2255
  if (hookFn == null) continue;
2256
+ const pluginContext = resolvePluginContext(context, plugin);
2162
2257
  try {
2163
2258
  logPluginHookStart(plugin, hook);
2164
- current = applyHookPayload(current, await invokePluginHook(hookFn, hook, current, context));
2259
+ current = applyHookPayload(current, await invokePluginHook(hookFn, hook, current, pluginContext));
2165
2260
  logPluginHookEnd(plugin, hook);
2166
2261
  } catch (error) {
2167
- reportPluginHookError(context, plugin, hook, error);
2262
+ reportPluginHookError(pluginContext, plugin, hook, error);
2168
2263
  throw error;
2169
2264
  }
2170
2265
  }
@@ -2184,12 +2279,13 @@ function execSyncHook(plugins, hook, payload, context = DEFAULT_PLUGIN_CONTEXT)
2184
2279
  for (const plugin of plugins) {
2185
2280
  const hookFn = getPluginHook(plugin, hook);
2186
2281
  if (hookFn == null) continue;
2282
+ const pluginContext = resolvePluginContext(context, plugin);
2187
2283
  try {
2188
2284
  logPluginHookStart(plugin, hook);
2189
- current = applyHookPayload(current, invokePluginHook(hookFn, hook, current, context));
2285
+ current = applyHookPayload(current, invokePluginHook(hookFn, hook, current, pluginContext));
2190
2286
  logPluginHookEnd(plugin, hook);
2191
2287
  } catch (error) {
2192
- reportPluginHookError(context, plugin, hook, error);
2288
+ reportPluginHookError(pluginContext, plugin, hook, error);
2193
2289
  throw error;
2194
2290
  }
2195
2291
  }
@@ -2200,19 +2296,60 @@ function execSyncHook(plugins, hook, payload, context = DEFAULT_PLUGIN_CONTEXT)
2200
2296
  * Creates an engine-local hook dispatcher bound to one diagnostic context.
2201
2297
  *
2202
2298
  * @internal
2299
+ * @remarks
2300
+ * Each dispatcher instance owns one plugin-context store: every plugin
2301
+ * definition gets exactly one `EnginePluginContext` (with `state` initialized
2302
+ * lazily via `createState()`) per dispatcher — i.e. per engine, since
2303
+ * `createEngine` creates one dispatcher per engine (#116). The same plugin
2304
+ * definition used with another dispatcher/engine gets a distinct context and
2305
+ * distinct state.
2203
2306
  */
2204
2307
  function createEngineHooks(context) {
2308
+ const pluginContexts = /* @__PURE__ */ new WeakMap();
2309
+ const host = context.host ?? {};
2310
+ const contextFor = (plugin) => {
2311
+ let entry = pluginContexts.get(plugin);
2312
+ if (entry == null) {
2313
+ try {
2314
+ entry = {
2315
+ status: "ok",
2316
+ context: {
2317
+ onDiagnostic: context.onDiagnostic,
2318
+ state: plugin.createState?.(),
2319
+ host
2320
+ }
2321
+ };
2322
+ } catch (error) {
2323
+ entry = {
2324
+ status: "failed",
2325
+ error
2326
+ };
2327
+ emitDiagnostic(context.onDiagnostic, {
2328
+ level: "error",
2329
+ code: "plugin-state-init-error",
2330
+ message: `Plugin "${plugin.name}" failed to initialize its engine-local state: ${error instanceof Error ? error.message : String(error)}`,
2331
+ cause: error,
2332
+ plugin: plugin.name
2333
+ });
2334
+ }
2335
+ pluginContexts.set(plugin, entry);
2336
+ }
2337
+ if (entry.status === "failed") throw entry.error;
2338
+ return entry.context;
2339
+ };
2205
2340
  return {
2206
- configureRawConfig: (plugins, config) => execAsyncHook(plugins, "configureRawConfig", config, context),
2207
- rawConfigConfigured: (plugins, config) => execSyncHook(plugins, "rawConfigConfigured", config, context),
2208
- configureResolvedConfig: (plugins, resolvedConfig) => execAsyncHook(plugins, "configureResolvedConfig", resolvedConfig, context),
2209
- configureEngine: (plugins, engine) => execAsyncHook(plugins, "configureEngine", engine, context),
2210
- transformSelectors: (plugins, selectors) => execAsyncHook(plugins, "transformSelectors", selectors, context),
2211
- transformStyleItems: (plugins, styleItems) => execAsyncHook(plugins, "transformStyleItems", styleItems, context),
2212
- transformStyleDefinitions: (plugins, styleDefinitions) => execAsyncHook(plugins, "transformStyleDefinitions", styleDefinitions, context),
2213
- preflightUpdated: (plugins) => execSyncHook(plugins, "preflightUpdated", void 0, context),
2214
- atomicStyleAdded: (plugins, atomicStyle) => execSyncHook(plugins, "atomicStyleAdded", atomicStyle, context),
2215
- autocompleteConfigUpdated: (plugins) => execSyncHook(plugins, "autocompleteConfigUpdated", void 0, context)
2341
+ configureRawConfig: (plugins, config) => execAsyncHook(plugins, "configureRawConfig", config, contextFor),
2342
+ rawConfigConfigured: (plugins, config) => execSyncHook(plugins, "rawConfigConfigured", config, contextFor),
2343
+ configureResolvedConfig: (plugins, resolvedConfig) => execAsyncHook(plugins, "configureResolvedConfig", resolvedConfig, contextFor),
2344
+ configureEngine: (plugins, engine) => execAsyncHook(plugins, "configureEngine", engine, contextFor),
2345
+ transformSelectors: (plugins, selectors) => execAsyncHook(plugins, "transformSelectors", selectors, contextFor),
2346
+ transformStyleItems: (plugins, styleItems) => execAsyncHook(plugins, "transformStyleItems", styleItems, contextFor),
2347
+ transformStyleDefinitions: (plugins, styleDefinitions) => execAsyncHook(plugins, "transformStyleDefinitions", styleDefinitions, contextFor),
2348
+ transformStyleContents: (plugins, styleContents) => execAsyncHook(plugins, "transformStyleContents", styleContents, contextFor),
2349
+ preflightUpdated: (plugins) => execSyncHook(plugins, "preflightUpdated", void 0, contextFor),
2350
+ atomicStyleAdded: (plugins, atomicStyle) => execSyncHook(plugins, "atomicStyleAdded", atomicStyle, contextFor),
2351
+ autocompleteConfigUpdated: (plugins) => execSyncHook(plugins, "autocompleteConfigUpdated", void 0, contextFor),
2352
+ configDependencyAdded: (plugins, path) => execSyncHook(plugins, "configDependencyAdded", path, contextFor)
2216
2353
  };
2217
2354
  }
2218
2355
  createEngineHooks(DEFAULT_PLUGIN_CONTEXT);
@@ -2235,6 +2372,10 @@ function resolvePlugins(plugins) {
2235
2372
  *
2236
2373
  * @param plugin - The plugin definition to return unchanged.
2237
2374
  * @returns The same plugin instance.
2375
+ *
2376
+ * @remarks
2377
+ * When the plugin declares `createState`, the state type is inferred from its
2378
+ * return value and every hook's `context.state` is typed accordingly.
2238
2379
  */
2239
2380
  function defineEnginePlugin(plugin) {
2240
2381
  return plugin;
@@ -3187,15 +3328,21 @@ const DEFAULT_LAYERS = {
3187
3328
  *
3188
3329
  * @remarks Core plugins (`important`, `variables`, `keyframes`, `selectors`, `shortcuts`) are prepended automatically. The function resolves plugins, runs all configuration hooks in sequence, and returns the ready-to-use engine.
3189
3330
  *
3331
+ * The caller-owned `config` graph is treated as immutable input (#117): the engine clones it into an engine-local working copy before any plugin configuration hook runs, so plugin hooks that mutate their config (`config.layers ??= {}` and friends) never write back into caller-owned objects, and the same config object can be reused across sequential or concurrent `createEngine()` calls without accumulating setup mutations. Ordinary config data (plain objects/arrays, `Map`/`Set` contents, `Date`, `RegExp`) is recursively isolated — module-augmented plugin fields included; functions and other opaque class instances keep their identity and are treated as immutable values; the `plugins` array is copied while plugin definition objects keep their identity (#116).
3332
+ *
3190
3333
  * @example
3191
3334
  * ```ts
3192
3335
  * const engine = await createEngine({ prefix: 'pk-', plugins: [myPlugin()] })
3193
3336
  * ```
3194
3337
  */
3195
3338
  async function createEngine(config = {}, options = {}) {
3339
+ config = cloneEngineConfig(config);
3196
3340
  const hostOnDiagnostic = options.onDiagnostic ?? noopDiagnosticHandler;
3197
3341
  const onDiagnostic = (diagnostic) => emitDiagnostic(hostOnDiagnostic, diagnostic);
3198
- const pluginHooks = createEngineHooks({ onDiagnostic });
3342
+ const pluginHooks = createEngineHooks({
3343
+ onDiagnostic,
3344
+ host: options.host ?? {}
3345
+ });
3199
3346
  log.debug("Creating engine with config:", config);
3200
3347
  const corePlugins = [
3201
3348
  variables(),
@@ -3316,7 +3463,7 @@ var Engine = class {
3316
3463
  *
3317
3464
  * @param path - The file path (ideally absolute) the current config was derived from.
3318
3465
  *
3319
- * @remarks Call from a plugin (typically in `configureEngine`) after loading data from disk. Integration layers watch registered paths and rebuild the engine when any of them changes.
3466
+ * @remarks Call from a plugin after loading data from disk — typically in `configureEngine`, but registering during later hooks (e.g. while resolving inside `engine.use()`) is fully supported: each genuinely new path fires the `configDependencyAdded` committed notification so integration layers can extend an already-running watcher (#122). Integration layers watch registered paths and rebuild the engine when any of them changes.
3320
3467
  *
3321
3468
  * @example
3322
3469
  * ```ts
@@ -3324,7 +3471,11 @@ var Engine = class {
3324
3471
  * ```
3325
3472
  */
3326
3473
  addConfigDependency(path) {
3474
+ if (this.configDependencies.has(path)) return;
3327
3475
  this.configDependencies.add(path);
3476
+ try {
3477
+ this.pluginHooks.configDependencyAdded(this.config.plugins, path);
3478
+ } catch {}
3328
3479
  }
3329
3480
  /**
3330
3481
  * Fires the `preflightUpdated` hook to notify plugins that preflight content has changed.
@@ -3345,7 +3496,7 @@ var Engine = class {
3345
3496
  *
3346
3497
  * @param atomicStyle - The atomic style that was just added to the store.
3347
3498
  *
3348
- * @remarks Called automatically by `use()` when a previously unseen atomic style is resolved.
3499
+ * @remarks Called automatically by `commitUse()` when a previously unseen atomic style is registered. This is a committed notification: the style's ID, cache keys, and store indices are already established, so mutating the payload is unsupported — plugins that need to transform styles must use the provisional hooks (`transformStyleItems`, `transformStyleDefinitions`, `transformSelectors`, `transformStyleContents`) instead (#114).
3349
3500
  *
3350
3501
  * @example
3351
3502
  * ```ts
@@ -3421,28 +3572,61 @@ var Engine = class {
3421
3572
  this.notifyPreflightUpdated();
3422
3573
  }
3423
3574
  /**
3424
- * Processes style items through the plugin pipeline and registers the resulting atomic styles in the store.
3575
+ * Provisionally resolves style items into a commit-ready plan without touching committed engine state.
3425
3576
  *
3426
3577
  * @param itemList - Style items to process: string references (shortcuts) and/or style definition objects.
3427
- * @returns An array containing any unresolved string references first, followed by atomic style IDs in resolution order.
3578
+ * @returns A promise of the {@link StyleUsePlan} to pass to `commitUse()`.
3428
3579
  *
3429
- * @remarks Runs `transformStyleItems` and `extractStyleDefinition` hooks, resolves each extracted content into an atomic style, deduplicates by base key, and fires `atomicStyleAdded` for new entries.
3580
+ * @remarks
3581
+ * Runs the full provisional pipeline: `transformStyleItems`, extraction
3582
+ * (`transformStyleDefinitions`/`transformSelectors`), normalization, and the
3583
+ * normalized-content seam `transformStyleContents`. It allocates no atomic
3584
+ * style IDs, mutates no `EngineStore` state, and fires no committed
3585
+ * notifications — a rejection anywhere leaves the engine exactly as it was.
3586
+ * Plans deliberately carry no IDs: reuse-vs-fresh decisions read live store
3587
+ * state and are only valid inside `commitUse()` (#114).
3430
3588
  *
3431
3589
  * @example
3432
3590
  * ```ts
3433
- * const ids = await engine.use({ color: 'red' }, { padding: '1rem' })
3591
+ * const plan = await engine.prepareUse({ color: 'red' })
3592
+ * const ids = engine.commitUse(plan)
3434
3593
  * ```
3435
3594
  */
3436
- async use(...itemList) {
3437
- log.debug(`Processing ${itemList.length} style items`);
3595
+ async prepareUse(...itemList) {
3596
+ log.debug(`Preparing ${itemList.length} style items`);
3438
3597
  const { unknown, contents } = await resolveStyleItemList({
3439
3598
  itemList,
3440
3599
  transformStyleItems: (styleItems) => this.pluginHooks.transformStyleItems(this.config.plugins, styleItems),
3441
3600
  extractStyleDefinition: (styleDefinition) => this.extract(styleDefinition)
3442
3601
  });
3602
+ return {
3603
+ unknown,
3604
+ contents: optimizeAtomicStyleContents(await this.pluginHooks.transformStyleContents(this.config.plugins, contents))
3605
+ };
3606
+ }
3607
+ /**
3608
+ * Commits a prepared plan: allocates/reuses atomic style IDs and registers new styles in the store.
3609
+ *
3610
+ * @param plan - A plan produced by `prepareUse()`.
3611
+ * @returns An array containing any unresolved string references first, followed by atomic style IDs in resolution order.
3612
+ *
3613
+ * @remarks
3614
+ * This is the short, mutation-critical section and MUST stay synchronous:
3615
+ * integration layers commit whole modules inside a revision/epoch-checked
3616
+ * synchronous block, so an `await` here would reopen the stale-commit race
3617
+ * (#114). `atomicStyleAdded` fires per newly registered style as a committed
3618
+ * notification; a throwing observer is reported through the diagnostic
3619
+ * context but never rolls back the already-committed registration.
3620
+ *
3621
+ * @example
3622
+ * ```ts
3623
+ * const ids = engine.commitUse(await engine.prepareUse({ color: 'red' }))
3624
+ * ```
3625
+ */
3626
+ commitUse(plan) {
3443
3627
  const resolvedIds = [];
3444
3628
  const resolvedIdsByBaseKey = /* @__PURE__ */ new Map();
3445
- for (const content of contents) {
3629
+ for (const content of plan.contents) {
3446
3630
  const { id, atomicStyle } = resolveAtomicStyle({
3447
3631
  content,
3448
3632
  prefix: this.config.prefix,
@@ -3453,11 +3637,29 @@ var Engine = class {
3453
3637
  resolvedIdsByBaseKey.set(getAtomicStyleBaseKey(content), id);
3454
3638
  if (atomicStyle != null) {
3455
3639
  log.debug(`Atomic style added: ${id}`);
3456
- this.notifyAtomicStyleAdded(atomicStyle);
3640
+ try {
3641
+ this.notifyAtomicStyleAdded(atomicStyle);
3642
+ } catch {}
3457
3643
  }
3458
3644
  }
3459
- log.debug(`Resolved ${resolvedIds.length} atomic styles, ${unknown.size} unknown items`);
3460
- return [...unknown, ...resolvedIds];
3645
+ log.debug(`Resolved ${resolvedIds.length} atomic styles, ${plan.unknown.size} unknown items`);
3646
+ return [...plan.unknown, ...resolvedIds];
3647
+ }
3648
+ /**
3649
+ * Processes style items through the plugin pipeline and registers the resulting atomic styles in the store.
3650
+ *
3651
+ * @param itemList - Style items to process: string references (shortcuts) and/or style definition objects.
3652
+ * @returns An array containing any unresolved string references first, followed by atomic style IDs in resolution order.
3653
+ *
3654
+ * @remarks Equivalent to `commitUse(await prepareUse(...itemList))` — the convenience path for direct consumers. Integration layers that need whole-module transactionality call the two phases separately (#114).
3655
+ *
3656
+ * @example
3657
+ * ```ts
3658
+ * const ids = await engine.use({ color: 'red' }, { padding: '1rem' })
3659
+ * ```
3660
+ */
3661
+ async use(...itemList) {
3662
+ return this.commitUse(await this.prepareUse(...itemList));
3461
3663
  }
3462
3664
  /**
3463
3665
  * Renders all registered preflight definitions into a CSS string.
@@ -3519,12 +3721,11 @@ var Engine = class {
3519
3721
  * Renders atomic styles into a CSS string, optionally filtered by ID and grouped by layer.
3520
3722
  *
3521
3723
  * @param isFormatted - Whether to produce human-readable CSS with newlines and indentation.
3522
- * @param options - Optional filtering: `atomicStyleIds` to render a subset, `isPreview` to use placeholder IDs.
3724
+ * @param options - Optional filtering: `atomicStyleIds` to render a subset.
3523
3725
  * @param options.atomicStyleIds - Specific atomic style IDs to render instead of the full store.
3524
- * @param options.isPreview - Whether to keep placeholder IDs instead of substituting real class names.
3525
3726
  * @returns The rendered atomic-style CSS.
3526
3727
  *
3527
- * @remarks Styles are sorted by rendering weight (selector specificity depth), grouped into configured `@layer` blocks, and rendered. When `isPreview` is true, atomic style IDs remain as placeholders for tooling previews.
3728
+ * @remarks Styles are sorted by rendering weight (selector specificity depth), grouped into configured `@layer` blocks, and rendered.
3528
3729
  *
3529
3730
  * @example
3530
3731
  * ```ts
@@ -3533,13 +3734,12 @@ var Engine = class {
3533
3734
  */
3534
3735
  async renderAtomicStyles(isFormatted, options = {}) {
3535
3736
  log.debug("Rendering atomic styles...");
3536
- const { atomicStyleIds = null, isPreview = false } = options;
3737
+ const { atomicStyleIds = null } = options;
3537
3738
  const atomicStyles = atomicStyleIds == null ? [...this.store.atomicStyles.values()] : atomicStyleIds.map((id) => this.store.atomicStyles.get(id)).filter(isNotNullish);
3538
- log.debug(`Rendering ${atomicStyles.length} atomic styles (preview: ${isPreview})`);
3739
+ log.debug(`Rendering ${atomicStyles.length} atomic styles`);
3539
3740
  reportUnknownAtomicStyleLayers(this, atomicStyles);
3540
3741
  return renderAtomicStyles({
3541
3742
  atomicStyles,
3542
- isPreview,
3543
3743
  isFormatted,
3544
3744
  defaultSelector: this.config.defaultSelector,
3545
3745
  layers: this.config.layers,
@@ -3834,13 +4034,13 @@ async function resolveStyleItemList({ itemList, transformStyleItems, extractStyl
3834
4034
  function sortAtomicStyles(styles, defaultSelector) {
3835
4035
  return [...styles].sort((a, b) => calcAtomicStyleRenderingWeight(a, defaultSelector) - calcAtomicStyleRenderingWeight(b, defaultSelector));
3836
4036
  }
3837
- function renderAtomicStylesCss({ atomicStyles, isPreview, isFormatted }) {
4037
+ function renderAtomicStylesCss({ atomicStyles, isFormatted }) {
3838
4038
  const blocks = /* @__PURE__ */ new Map();
3839
4039
  atomicStyles.forEach(({ id, content: { selector: rawSelector, property, value } }) => {
3840
4040
  const { selector } = splitLayerSelector(rawSelector);
3841
4041
  if (selector.some((s) => hasAtomicStyleIdPlaceholder(s)) === false || value == null) return;
3842
4042
  const renderObject = {
3843
- selector: isPreview ? selector : selector.map((s) => replaceAtomicStyleIdPlaceholder(s, id)),
4043
+ selector: selector.map((s) => replaceAtomicStyleIdPlaceholder(s, id)),
3844
4044
  properties: value.map((v) => ({
3845
4045
  property,
3846
4046
  value: v
@@ -3863,9 +4063,8 @@ function renderAtomicStylesCss({ atomicStyles, isPreview, isFormatted }) {
3863
4063
  * Standalone function that renders atomic styles into CSS with layer grouping.
3864
4064
  * @internal
3865
4065
  *
3866
- * @param payload - An object containing `atomicStyles`, `isPreview`, `isFormatted`, `defaultSelector`, and optional `layers`/`defaultUtilitiesLayer`.
4066
+ * @param payload - An object containing `atomicStyles`, `isFormatted`, `defaultSelector`, and optional `layers`/`defaultUtilitiesLayer`.
3867
4067
  * @param payload.atomicStyles - The atomic styles to render.
3868
- * @param payload.isPreview - Whether placeholder IDs should be preserved for preview output.
3869
4068
  * @param payload.isFormatted - Whether to render with indentation and line breaks.
3870
4069
  * @param payload.defaultSelector - The engine default selector used when computing render order.
3871
4070
  * @param payload.layers - Optional configured CSS layers to group atomic styles into.
@@ -3876,15 +4075,14 @@ function renderAtomicStylesCss({ atomicStyles, isPreview, isFormatted }) {
3876
4075
  *
3877
4076
  * @example
3878
4077
  * ```ts
3879
- * const css = renderAtomicStyles({ atomicStyles, isPreview: false, isFormatted: true, defaultSelector: '.pk-__ID__', layers: { utilities: 10 } })
4078
+ * const css = renderAtomicStyles({ atomicStyles, isFormatted: true, defaultSelector: '.pk-__ID__', layers: { utilities: 10 } })
3880
4079
  * ```
3881
4080
  */
3882
4081
  function renderAtomicStyles(payload) {
3883
- const { atomicStyles, isPreview, isFormatted, defaultSelector, layers, defaultUtilitiesLayer } = payload;
4082
+ const { atomicStyles, isFormatted, defaultSelector, layers, defaultUtilitiesLayer } = payload;
3884
4083
  const sortedStyles = sortAtomicStyles(atomicStyles, defaultSelector);
3885
4084
  if (layers == null) return renderAtomicStylesCss({
3886
4085
  atomicStyles: sortedStyles,
3887
- isPreview,
3888
4086
  isFormatted
3889
4087
  });
3890
4088
  const layerOrder = sortLayerNames(layers);
@@ -3897,7 +4095,6 @@ function renderAtomicStyles(payload) {
3897
4095
  const parts = [];
3898
4096
  if (unlayeredStyles.length > 0) parts.push(renderAtomicStylesCss({
3899
4097
  atomicStyles: unlayeredStyles,
3900
- isPreview,
3901
4098
  isFormatted
3902
4099
  }));
3903
4100
  parts.push(...renderLayerBlocks({
@@ -3906,7 +4103,6 @@ function renderAtomicStyles(payload) {
3906
4103
  isFormatted,
3907
4104
  render: (styles) => renderAtomicStylesCss({
3908
4105
  atomicStyles: styles,
3909
- isPreview,
3910
4106
  isFormatted
3911
4107
  })
3912
4108
  }));
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@pikacss/core",
3
3
  "type": "module",
4
- "version": "0.0.61",
4
+ "version": "0.0.62",
5
5
  "author": "DevilTea <ch19980814@gmail.com>",
6
6
  "license": "MIT",
7
7
  "homepage": "https://pikacss.github.io",