@zag-js/core 1.37.0 → 1.38.1

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/state.js CHANGED
@@ -30,6 +30,7 @@ __export(state_exports, {
30
30
  resolveStateValue: () => resolveStateValue
31
31
  });
32
32
  module.exports = __toCommonJS(state_exports);
33
+ var import_utils = require("@zag-js/utils");
33
34
  var STATE_DELIMITER = ".";
34
35
  var ABSOLUTE_PREFIX = "#";
35
36
  var stateIndexCache = /* @__PURE__ */ new WeakMap();
@@ -43,6 +44,9 @@ function isAbsoluteStatePath(value) {
43
44
  function isExplicitAbsoluteStatePath(value) {
44
45
  return value.startsWith(ABSOLUTE_PREFIX);
45
46
  }
47
+ function isChildTarget(value) {
48
+ return value.startsWith(STATE_DELIMITER);
49
+ }
46
50
  function stripAbsolutePrefix(value) {
47
51
  return isExplicitAbsoluteStatePath(value) ? value.slice(ABSOLUTE_PREFIX.length) : value;
48
52
  }
@@ -57,12 +61,18 @@ function buildStateIndex(machine) {
57
61
  const stateId = state.id;
58
62
  if (stateId) {
59
63
  if (idIndex.has(stateId)) {
60
- throw new Error(`Duplicate state id: ${stateId}`);
64
+ (0, import_utils.invariant)(`[zag-js] Duplicate state id: "${stateId}"`);
61
65
  }
62
66
  idIndex.set(stateId, basePath);
63
67
  }
64
68
  const childStates = state.states;
65
69
  if (!childStates) return;
70
+ (0, import_utils.ensure)(state.initial, () => `[zag-js] Compound state "${basePath}" has child states but no "initial" property`);
71
+ if (!(state.initial in childStates)) {
72
+ (0, import_utils.invariant)(
73
+ `[zag-js] Compound state "${basePath}" has initial "${String(state.initial)}" which is not a child state`
74
+ );
75
+ }
66
76
  for (const [childKey, childState] of Object.entries(childStates)) {
67
77
  if (!childState) continue;
68
78
  const childPath = appendStatePath(basePath, childKey);
@@ -136,18 +146,21 @@ function resolveStateValue(machine, value, source) {
136
146
  if (isExplicitAbsoluteStatePath(stateValue)) {
137
147
  const stateId = stripAbsolutePrefix(stateValue);
138
148
  const statePath = getStatePathById(machine, stateId);
139
- if (!statePath) {
140
- throw new Error(`Unknown state id: ${stateId}`);
141
- }
149
+ (0, import_utils.ensure)(statePath, () => `[zag-js] Unknown state id: "${stateId}"`);
142
150
  return resolveAbsoluteStateValue(machine, statePath);
143
151
  }
152
+ if (isChildTarget(stateValue) && source) {
153
+ const childPath = appendStatePath(source, stateValue.slice(1));
154
+ return resolveAbsoluteStateValue(machine, childPath);
155
+ }
144
156
  if (!isAbsoluteStatePath(stateValue) && source) {
145
157
  const sourceSegments = toSegments(source);
146
- for (let index = sourceSegments.length; index >= 1; index--) {
158
+ for (let index = sourceSegments.length - 1; index >= 1; index--) {
147
159
  const base = sourceSegments.slice(0, index).join(STATE_DELIMITER);
148
160
  const candidate = appendStatePath(base, stateValue);
149
161
  if (hasStatePath(machine, candidate)) return resolveAbsoluteStateValue(machine, candidate);
150
162
  }
163
+ if (hasStatePath(machine, stateValue)) return resolveAbsoluteStateValue(machine, stateValue);
151
164
  }
152
165
  return resolveAbsoluteStateValue(machine, stateValue);
153
166
  }
package/dist/state.mjs CHANGED
@@ -1,4 +1,5 @@
1
1
  // src/state.ts
2
+ import { ensure, invariant } from "@zag-js/utils";
2
3
  var STATE_DELIMITER = ".";
3
4
  var ABSOLUTE_PREFIX = "#";
4
5
  var stateIndexCache = /* @__PURE__ */ new WeakMap();
@@ -12,6 +13,9 @@ function isAbsoluteStatePath(value) {
12
13
  function isExplicitAbsoluteStatePath(value) {
13
14
  return value.startsWith(ABSOLUTE_PREFIX);
14
15
  }
16
+ function isChildTarget(value) {
17
+ return value.startsWith(STATE_DELIMITER);
18
+ }
15
19
  function stripAbsolutePrefix(value) {
16
20
  return isExplicitAbsoluteStatePath(value) ? value.slice(ABSOLUTE_PREFIX.length) : value;
17
21
  }
@@ -26,12 +30,18 @@ function buildStateIndex(machine) {
26
30
  const stateId = state.id;
27
31
  if (stateId) {
28
32
  if (idIndex.has(stateId)) {
29
- throw new Error(`Duplicate state id: ${stateId}`);
33
+ invariant(`[zag-js] Duplicate state id: "${stateId}"`);
30
34
  }
31
35
  idIndex.set(stateId, basePath);
32
36
  }
33
37
  const childStates = state.states;
34
38
  if (!childStates) return;
39
+ ensure(state.initial, () => `[zag-js] Compound state "${basePath}" has child states but no "initial" property`);
40
+ if (!(state.initial in childStates)) {
41
+ invariant(
42
+ `[zag-js] Compound state "${basePath}" has initial "${String(state.initial)}" which is not a child state`
43
+ );
44
+ }
35
45
  for (const [childKey, childState] of Object.entries(childStates)) {
36
46
  if (!childState) continue;
37
47
  const childPath = appendStatePath(basePath, childKey);
@@ -105,18 +115,21 @@ function resolveStateValue(machine, value, source) {
105
115
  if (isExplicitAbsoluteStatePath(stateValue)) {
106
116
  const stateId = stripAbsolutePrefix(stateValue);
107
117
  const statePath = getStatePathById(machine, stateId);
108
- if (!statePath) {
109
- throw new Error(`Unknown state id: ${stateId}`);
110
- }
118
+ ensure(statePath, () => `[zag-js] Unknown state id: "${stateId}"`);
111
119
  return resolveAbsoluteStateValue(machine, statePath);
112
120
  }
121
+ if (isChildTarget(stateValue) && source) {
122
+ const childPath = appendStatePath(source, stateValue.slice(1));
123
+ return resolveAbsoluteStateValue(machine, childPath);
124
+ }
113
125
  if (!isAbsoluteStatePath(stateValue) && source) {
114
126
  const sourceSegments = toSegments(source);
115
- for (let index = sourceSegments.length; index >= 1; index--) {
127
+ for (let index = sourceSegments.length - 1; index >= 1; index--) {
116
128
  const base = sourceSegments.slice(0, index).join(STATE_DELIMITER);
117
129
  const candidate = appendStatePath(base, stateValue);
118
130
  if (hasStatePath(machine, candidate)) return resolveAbsoluteStateValue(machine, candidate);
119
131
  }
132
+ if (hasStatePath(machine, stateValue)) return resolveAbsoluteStateValue(machine, stateValue);
120
133
  }
121
134
  return resolveAbsoluteStateValue(machine, stateValue);
122
135
  }
package/dist/types.d.mts CHANGED
@@ -108,10 +108,11 @@ type TopLevelState<S extends string> = S extends `${infer Top}.${string}` ? Top
108
108
  type ChildStateKey<S extends string, Parent extends string> = S extends `${Parent}.${infer Rest}` ? Rest extends `${infer Child}.${string}` ? Child : Rest : never;
109
109
  type ParentPath<S extends string> = S extends `${infer Parent}.${string}` ? Parent : never;
110
110
  type AncestorPaths<S extends string> = S | (ParentPath<S> extends never ? never : AncestorPaths<ParentPath<S>>);
111
- type RelativeStateTarget<S extends string, Source extends string> = ChildStateKey<S, AncestorPaths<Source>>;
112
111
  type StateIdTarget = `#${string}`;
112
+ type SiblingStateTarget<S extends string, Source extends string> = TopLevelState<S> | ChildStateKey<S, Exclude<AncestorPaths<Source>, Source>>;
113
+ type ChildStateTarget<S extends string, Source extends string> = `.${ChildStateKey<S, Source>}`;
113
114
  interface Transition<T extends Dict, Source extends string | undefined = string | undefined> {
114
- target?: T["state"] | StateIdTarget | (Source extends string ? RelativeStateTarget<T["state"], Source> : never) | undefined;
115
+ target?: T["state"] | StateIdTarget | (Source extends string ? SiblingStateTarget<T["state"], Source> : never) | (Source extends string ? ChildStateTarget<T["state"], Source> : never) | undefined;
115
116
  actions?: T["action"][] | undefined;
116
117
  guard?: T["guard"] | GuardFn<T> | undefined;
117
118
  reenter?: boolean | undefined;
package/dist/types.d.ts CHANGED
@@ -108,10 +108,11 @@ type TopLevelState<S extends string> = S extends `${infer Top}.${string}` ? Top
108
108
  type ChildStateKey<S extends string, Parent extends string> = S extends `${Parent}.${infer Rest}` ? Rest extends `${infer Child}.${string}` ? Child : Rest : never;
109
109
  type ParentPath<S extends string> = S extends `${infer Parent}.${string}` ? Parent : never;
110
110
  type AncestorPaths<S extends string> = S | (ParentPath<S> extends never ? never : AncestorPaths<ParentPath<S>>);
111
- type RelativeStateTarget<S extends string, Source extends string> = ChildStateKey<S, AncestorPaths<Source>>;
112
111
  type StateIdTarget = `#${string}`;
112
+ type SiblingStateTarget<S extends string, Source extends string> = TopLevelState<S> | ChildStateKey<S, Exclude<AncestorPaths<Source>, Source>>;
113
+ type ChildStateTarget<S extends string, Source extends string> = `.${ChildStateKey<S, Source>}`;
113
114
  interface Transition<T extends Dict, Source extends string | undefined = string | undefined> {
114
- target?: T["state"] | StateIdTarget | (Source extends string ? RelativeStateTarget<T["state"], Source> : never) | undefined;
115
+ target?: T["state"] | StateIdTarget | (Source extends string ? SiblingStateTarget<T["state"], Source> : never) | (Source extends string ? ChildStateTarget<T["state"], Source> : never) | undefined;
115
116
  actions?: T["action"][] | undefined;
116
117
  guard?: T["guard"] | GuardFn<T> | undefined;
117
118
  reenter?: boolean | undefined;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zag-js/core",
3
- "version": "1.37.0",
3
+ "version": "1.38.1",
4
4
  "description": "A minimal implementation of xstate fsm for UI machines",
5
5
  "keywords": [
6
6
  "ui-machines",
@@ -25,8 +25,8 @@
25
25
  "url": "https://github.com/chakra-ui/zag/issues"
26
26
  },
27
27
  "dependencies": {
28
- "@zag-js/utils": "1.37.0",
29
- "@zag-js/dom-query": "1.37.0"
28
+ "@zag-js/utils": "1.38.1",
29
+ "@zag-js/dom-query": "1.38.1"
30
30
  },
31
31
  "devDependencies": {
32
32
  "clean-package": "2.2.0"