svelte-origin 1.0.0-next.17 → 1.0.0-next.19

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/cli.js CHANGED
@@ -2065,7 +2065,32 @@ function transformOriginBody(content, parents = [], attrDetails = [], propName =
2065
2065
  ` + `})`);
2066
2066
  }
2067
2067
  } else {
2068
- propsLines.push("const __props = __inputAttrs");
2068
+ propsLines.push("let __props = $state({ ...__inputAttrs })", "const __syncState = new Map()", `$effect.pre(() => {
2069
+ ` + ` // Bidirectional sync between __inputAttrs and __props
2070
+ ` + ` for (const key of Object.keys(__inputAttrs)) {
2071
+ ` + ` const parentVal = __inputAttrs[key]
2072
+ ` + ` const localVal = __props[key]
2073
+ ` + ` const state = __syncState.get(key) ?? { parent: parentVal, local: localVal }
2074
+ ` + ` __syncState.set(key, state)
2075
+
2076
+ ` + ` // Parent changed -> update local
2077
+ ` + ` if (parentVal !== state.parent) {
2078
+ ` + ` state.parent = parentVal
2079
+ ` + ` if (localVal !== parentVal) {
2080
+ ` + ` __props[key] = parentVal
2081
+ ` + ` state.local = parentVal
2082
+ ` + ` }
2083
+ ` + ` continue
2084
+ ` + ` }
2085
+
2086
+ ` + ` // Local changed -> update parent (for bindable props)
2087
+ ` + ` if (localVal !== state.local) {
2088
+ ` + ` state.local = localVal
2089
+ ` + ` try { __inputAttrs[key] = localVal } catch {}
2090
+ ` + ` state.parent = __inputAttrs[key]
2091
+ ` + ` }
2092
+ ` + ` }
2093
+ ` + ` })`);
2069
2094
  }
2070
2095
  const propsObjectCode = "\t\t" + propsLines.join(`
2071
2096
  `);
@@ -2945,6 +2970,9 @@ async function transformScriptContent(source, options) {
2945
2970
  var EXTENSIONS = [".svelte", ".svelte.ts", ".svelte.js", ".js", ".ts"];
2946
2971
  function cleanupForLibrary(code, schemaCache) {
2947
2972
  let result = code;
2973
+ result = result.replace(/(?:var|const|let)\s+\$\w+\s*=\s*globalThis\.\$\w+(?:\s*,\s*\$\w+\s*=\s*globalThis\.\$\w+)*\s*;?\n?/g, "");
2974
+ result = result.replace(/(?:var|const|let)\s*\{\s*\$origin\s*(?:,\s*\$\w+\s*)*\}\s*=\s*globalThis\s*;?\n?/g, "");
2975
+ result = result.replace(/\/\/\s*@ts-ignore\s*-?\s*macros are transformed at build time\n?/g, "");
2948
2976
  result = result.replace(/\ntype \$\$Props = \$attrs\.Of<[^>]+>\n/g, `
2949
2977
  `);
2950
2978
  const attrsOfPattern = /(\}\s*:\s*)\$attrs\.Of<typeof (\w+)>(\s*=\s*\$props\(\))/g;
@@ -3075,10 +3103,12 @@ async function postProcess(options) {
3075
3103
  isComponent,
3076
3104
  schemaResolver
3077
3105
  });
3078
- if (transformed.changed) {
3106
+ let finalCode = cleanupForLibrary(transformed.changed ? transformed.code : source, schemaCache);
3107
+ const sourceToCompare = transformed.changed ? transformed.code : source;
3108
+ const cleanupChanged = finalCode !== sourceToCompare;
3109
+ if (transformed.changed || cleanupChanged) {
3079
3110
  result.filesProcessed++;
3080
3111
  result.files.push(filePath);
3081
- let finalCode = cleanupForLibrary(transformed.code, schemaCache);
3082
3112
  if (!dryRun) {
3083
3113
  fs.writeFileSync(filePath, finalCode, "utf-8");
3084
3114
  }
package/dist/index.js CHANGED
@@ -6153,7 +6153,32 @@ function transformOriginBody(content, parents = [], attrDetails = [], propName =
6153
6153
  ` + `})`);
6154
6154
  }
6155
6155
  } else {
6156
- propsLines.push("const __props = __inputAttrs");
6156
+ propsLines.push("let __props = $state({ ...__inputAttrs })", "const __syncState = new Map()", `$effect.pre(() => {
6157
+ ` + ` // Bidirectional sync between __inputAttrs and __props
6158
+ ` + ` for (const key of Object.keys(__inputAttrs)) {
6159
+ ` + ` const parentVal = __inputAttrs[key]
6160
+ ` + ` const localVal = __props[key]
6161
+ ` + ` const state = __syncState.get(key) ?? { parent: parentVal, local: localVal }
6162
+ ` + ` __syncState.set(key, state)
6163
+
6164
+ ` + ` // Parent changed -> update local
6165
+ ` + ` if (parentVal !== state.parent) {
6166
+ ` + ` state.parent = parentVal
6167
+ ` + ` if (localVal !== parentVal) {
6168
+ ` + ` __props[key] = parentVal
6169
+ ` + ` state.local = parentVal
6170
+ ` + ` }
6171
+ ` + ` continue
6172
+ ` + ` }
6173
+
6174
+ ` + ` // Local changed -> update parent (for bindable props)
6175
+ ` + ` if (localVal !== state.local) {
6176
+ ` + ` state.local = localVal
6177
+ ` + ` try { __inputAttrs[key] = localVal } catch {}
6178
+ ` + ` state.parent = __inputAttrs[key]
6179
+ ` + ` }
6180
+ ` + ` }
6181
+ ` + ` })`);
6157
6182
  }
6158
6183
  const propsObjectCode = "\t\t" + propsLines.join(`
6159
6184
  `);
package/dist/plugin.js CHANGED
@@ -2059,7 +2059,32 @@ function transformOriginBody(content, parents = [], attrDetails = [], propName =
2059
2059
  ` + `})`);
2060
2060
  }
2061
2061
  } else {
2062
- propsLines.push("const __props = __inputAttrs");
2062
+ propsLines.push("let __props = $state({ ...__inputAttrs })", "const __syncState = new Map()", `$effect.pre(() => {
2063
+ ` + ` // Bidirectional sync between __inputAttrs and __props
2064
+ ` + ` for (const key of Object.keys(__inputAttrs)) {
2065
+ ` + ` const parentVal = __inputAttrs[key]
2066
+ ` + ` const localVal = __props[key]
2067
+ ` + ` const state = __syncState.get(key) ?? { parent: parentVal, local: localVal }
2068
+ ` + ` __syncState.set(key, state)
2069
+
2070
+ ` + ` // Parent changed -> update local
2071
+ ` + ` if (parentVal !== state.parent) {
2072
+ ` + ` state.parent = parentVal
2073
+ ` + ` if (localVal !== parentVal) {
2074
+ ` + ` __props[key] = parentVal
2075
+ ` + ` state.local = parentVal
2076
+ ` + ` }
2077
+ ` + ` continue
2078
+ ` + ` }
2079
+
2080
+ ` + ` // Local changed -> update parent (for bindable props)
2081
+ ` + ` if (localVal !== state.local) {
2082
+ ` + ` state.local = localVal
2083
+ ` + ` try { __inputAttrs[key] = localVal } catch {}
2084
+ ` + ` state.parent = __inputAttrs[key]
2085
+ ` + ` }
2086
+ ` + ` }
2087
+ ` + ` })`);
2063
2088
  }
2064
2089
  const propsObjectCode = "\t\t" + propsLines.join(`
2065
2090
  `);
@@ -2063,7 +2063,32 @@ function transformOriginBody(content, parents = [], attrDetails = [], propName =
2063
2063
  ` + `})`);
2064
2064
  }
2065
2065
  } else {
2066
- propsLines.push("const __props = __inputAttrs");
2066
+ propsLines.push("let __props = $state({ ...__inputAttrs })", "const __syncState = new Map()", `$effect.pre(() => {
2067
+ ` + ` // Bidirectional sync between __inputAttrs and __props
2068
+ ` + ` for (const key of Object.keys(__inputAttrs)) {
2069
+ ` + ` const parentVal = __inputAttrs[key]
2070
+ ` + ` const localVal = __props[key]
2071
+ ` + ` const state = __syncState.get(key) ?? { parent: parentVal, local: localVal }
2072
+ ` + ` __syncState.set(key, state)
2073
+
2074
+ ` + ` // Parent changed -> update local
2075
+ ` + ` if (parentVal !== state.parent) {
2076
+ ` + ` state.parent = parentVal
2077
+ ` + ` if (localVal !== parentVal) {
2078
+ ` + ` __props[key] = parentVal
2079
+ ` + ` state.local = parentVal
2080
+ ` + ` }
2081
+ ` + ` continue
2082
+ ` + ` }
2083
+
2084
+ ` + ` // Local changed -> update parent (for bindable props)
2085
+ ` + ` if (localVal !== state.local) {
2086
+ ` + ` state.local = localVal
2087
+ ` + ` try { __inputAttrs[key] = localVal } catch {}
2088
+ ` + ` state.parent = __inputAttrs[key]
2089
+ ` + ` }
2090
+ ` + ` }
2091
+ ` + ` })`);
2067
2092
  }
2068
2093
  const propsObjectCode = "\t\t" + propsLines.join(`
2069
2094
  `);
@@ -2943,6 +2968,9 @@ async function transformScriptContent(source, options) {
2943
2968
  var EXTENSIONS = [".svelte", ".svelte.ts", ".svelte.js", ".js", ".ts"];
2944
2969
  function cleanupForLibrary(code, schemaCache) {
2945
2970
  let result = code;
2971
+ result = result.replace(/(?:var|const|let)\s+\$\w+\s*=\s*globalThis\.\$\w+(?:\s*,\s*\$\w+\s*=\s*globalThis\.\$\w+)*\s*;?\n?/g, "");
2972
+ result = result.replace(/(?:var|const|let)\s*\{\s*\$origin\s*(?:,\s*\$\w+\s*)*\}\s*=\s*globalThis\s*;?\n?/g, "");
2973
+ result = result.replace(/\/\/\s*@ts-ignore\s*-?\s*macros are transformed at build time\n?/g, "");
2946
2974
  result = result.replace(/\ntype \$\$Props = \$attrs\.Of<[^>]+>\n/g, `
2947
2975
  `);
2948
2976
  const attrsOfPattern = /(\}\s*:\s*)\$attrs\.Of<typeof (\w+)>(\s*=\s*\$props\(\))/g;
@@ -3073,10 +3101,12 @@ async function postProcess(options) {
3073
3101
  isComponent,
3074
3102
  schemaResolver
3075
3103
  });
3076
- if (transformed.changed) {
3104
+ let finalCode = cleanupForLibrary(transformed.changed ? transformed.code : source, schemaCache);
3105
+ const sourceToCompare = transformed.changed ? transformed.code : source;
3106
+ const cleanupChanged = finalCode !== sourceToCompare;
3107
+ if (transformed.changed || cleanupChanged) {
3077
3108
  result.filesProcessed++;
3078
3109
  result.files.push(filePath);
3079
- let finalCode = cleanupForLibrary(transformed.code, schemaCache);
3080
3110
  if (!dryRun) {
3081
3111
  fs.writeFileSync(filePath, finalCode, "utf-8");
3082
3112
  }
@@ -2059,7 +2059,32 @@ function transformOriginBody(content, parents = [], attrDetails = [], propName =
2059
2059
  ` + `})`);
2060
2060
  }
2061
2061
  } else {
2062
- propsLines.push("const __props = __inputAttrs");
2062
+ propsLines.push("let __props = $state({ ...__inputAttrs })", "const __syncState = new Map()", `$effect.pre(() => {
2063
+ ` + ` // Bidirectional sync between __inputAttrs and __props
2064
+ ` + ` for (const key of Object.keys(__inputAttrs)) {
2065
+ ` + ` const parentVal = __inputAttrs[key]
2066
+ ` + ` const localVal = __props[key]
2067
+ ` + ` const state = __syncState.get(key) ?? { parent: parentVal, local: localVal }
2068
+ ` + ` __syncState.set(key, state)
2069
+
2070
+ ` + ` // Parent changed -> update local
2071
+ ` + ` if (parentVal !== state.parent) {
2072
+ ` + ` state.parent = parentVal
2073
+ ` + ` if (localVal !== parentVal) {
2074
+ ` + ` __props[key] = parentVal
2075
+ ` + ` state.local = parentVal
2076
+ ` + ` }
2077
+ ` + ` continue
2078
+ ` + ` }
2079
+
2080
+ ` + ` // Local changed -> update parent (for bindable props)
2081
+ ` + ` if (localVal !== state.local) {
2082
+ ` + ` state.local = localVal
2083
+ ` + ` try { __inputAttrs[key] = localVal } catch {}
2084
+ ` + ` state.parent = __inputAttrs[key]
2085
+ ` + ` }
2086
+ ` + ` }
2087
+ ` + ` })`);
2063
2088
  }
2064
2089
  const propsObjectCode = "\t\t" + propsLines.join(`
2065
2090
  `);
@@ -75,7 +75,7 @@ export type UnwrapBindable<T> = T extends Bindable<infer U> ? U : T;
75
75
  */
76
76
  export interface OriginFactory<TInstance = unknown, TAttrs = Record<string, any>> {
77
77
  /** Create an instance with the given reactive attrs and optional init args */
78
- (attrs?: TAttrs | null, ...initArgs: any[]): TInstance;
78
+ (attrs?: TAttrs | null, ...initArgs: any[]): TInstance & OriginInstanceExtras;
79
79
  /** Marker to identify origin factories */
80
80
  readonly __origin: true;
81
81
  /** The attr schema extracted from the definition */
@@ -113,13 +113,33 @@ export interface AttrsFactory<_TAttrs = Record<string, any>> {
113
113
  /** Parent attr factories (for inheritance) */
114
114
  readonly __parents: AttrsFactory<any>[];
115
115
  }
116
+ /**
117
+ * Attachment registry returned by $attachments getter.
118
+ * Maps Symbol keys to attachment functions.
119
+ */
120
+ export type AttachmentRegistry = Record<symbol, (element: Element) => void | (() => void)>;
121
+ /**
122
+ * Properties added to all origin instances at runtime.
123
+ * These are injected by __createOrigin after __create returns.
124
+ */
125
+ export interface OriginInstanceExtras {
126
+ /**
127
+ * Attachment functions that can be spread onto elements.
128
+ * Returns an object with Symbol keys mapping to attachment functions.
129
+ *
130
+ * @example
131
+ * <div {...instance.$attachments}>
132
+ */
133
+ readonly $attachments: AttachmentRegistry;
134
+ }
116
135
  /**
117
136
  * The origin instance has:
118
137
  * - attrs: reactive attrs object (passed in)
119
138
  * - super: parent instance (if extending)
139
+ * - $attachments: attachment registry (injected by runtime)
120
140
  * - All other members from the definition (state, getters, methods)
121
141
  */
122
- export interface OriginInstance<TAttrs = Record<string, any>> {
142
+ export interface OriginInstance<TAttrs = Record<string, any>> extends OriginInstanceExtras {
123
143
  /** Reactive attrs object */
124
144
  readonly attrs: TAttrs;
125
145
  /** Parent instance (if extending) */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "svelte-origin",
3
- "version": "1.0.0-next.17",
3
+ "version": "1.0.0-next.19",
4
4
  "description": "Compiler-assisted state and prop ergonomics for Svelte 5",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",