stellar-drive 1.0.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.
Files changed (246) hide show
  1. package/README.md +607 -0
  2. package/dist/actions/remoteChange.d.ts +204 -0
  3. package/dist/actions/remoteChange.d.ts.map +1 -0
  4. package/dist/actions/remoteChange.js +424 -0
  5. package/dist/actions/remoteChange.js.map +1 -0
  6. package/dist/actions/truncateTooltip.d.ts +56 -0
  7. package/dist/actions/truncateTooltip.d.ts.map +1 -0
  8. package/dist/actions/truncateTooltip.js +312 -0
  9. package/dist/actions/truncateTooltip.js.map +1 -0
  10. package/dist/auth/crypto.d.ts +41 -0
  11. package/dist/auth/crypto.d.ts.map +1 -0
  12. package/dist/auth/crypto.js +50 -0
  13. package/dist/auth/crypto.js.map +1 -0
  14. package/dist/auth/deviceVerification.d.ts +283 -0
  15. package/dist/auth/deviceVerification.d.ts.map +1 -0
  16. package/dist/auth/deviceVerification.js +575 -0
  17. package/dist/auth/deviceVerification.js.map +1 -0
  18. package/dist/auth/displayUtils.d.ts +98 -0
  19. package/dist/auth/displayUtils.d.ts.map +1 -0
  20. package/dist/auth/displayUtils.js +145 -0
  21. package/dist/auth/displayUtils.js.map +1 -0
  22. package/dist/auth/loginGuard.d.ts +134 -0
  23. package/dist/auth/loginGuard.d.ts.map +1 -0
  24. package/dist/auth/loginGuard.js +276 -0
  25. package/dist/auth/loginGuard.js.map +1 -0
  26. package/dist/auth/offlineCredentials.d.ts +105 -0
  27. package/dist/auth/offlineCredentials.d.ts.map +1 -0
  28. package/dist/auth/offlineCredentials.js +176 -0
  29. package/dist/auth/offlineCredentials.js.map +1 -0
  30. package/dist/auth/offlineSession.d.ts +96 -0
  31. package/dist/auth/offlineSession.d.ts.map +1 -0
  32. package/dist/auth/offlineSession.js +145 -0
  33. package/dist/auth/offlineSession.js.map +1 -0
  34. package/dist/auth/resolveAuthState.d.ts +85 -0
  35. package/dist/auth/resolveAuthState.d.ts.map +1 -0
  36. package/dist/auth/resolveAuthState.js +249 -0
  37. package/dist/auth/resolveAuthState.js.map +1 -0
  38. package/dist/auth/singleUser.d.ts +498 -0
  39. package/dist/auth/singleUser.d.ts.map +1 -0
  40. package/dist/auth/singleUser.js +1282 -0
  41. package/dist/auth/singleUser.js.map +1 -0
  42. package/dist/bin/commands.d.ts +14 -0
  43. package/dist/bin/commands.d.ts.map +1 -0
  44. package/dist/bin/commands.js +68 -0
  45. package/dist/bin/commands.js.map +1 -0
  46. package/dist/bin/install-pwa.d.ts +41 -0
  47. package/dist/bin/install-pwa.d.ts.map +1 -0
  48. package/dist/bin/install-pwa.js +4594 -0
  49. package/dist/bin/install-pwa.js.map +1 -0
  50. package/dist/config.d.ts +249 -0
  51. package/dist/config.d.ts.map +1 -0
  52. package/dist/config.js +395 -0
  53. package/dist/config.js.map +1 -0
  54. package/dist/conflicts.d.ts +306 -0
  55. package/dist/conflicts.d.ts.map +1 -0
  56. package/dist/conflicts.js +807 -0
  57. package/dist/conflicts.js.map +1 -0
  58. package/dist/crdt/awareness.d.ts +128 -0
  59. package/dist/crdt/awareness.d.ts.map +1 -0
  60. package/dist/crdt/awareness.js +284 -0
  61. package/dist/crdt/awareness.js.map +1 -0
  62. package/dist/crdt/channel.d.ts +165 -0
  63. package/dist/crdt/channel.d.ts.map +1 -0
  64. package/dist/crdt/channel.js +522 -0
  65. package/dist/crdt/channel.js.map +1 -0
  66. package/dist/crdt/config.d.ts +58 -0
  67. package/dist/crdt/config.d.ts.map +1 -0
  68. package/dist/crdt/config.js +123 -0
  69. package/dist/crdt/config.js.map +1 -0
  70. package/dist/crdt/helpers.d.ts +104 -0
  71. package/dist/crdt/helpers.d.ts.map +1 -0
  72. package/dist/crdt/helpers.js +116 -0
  73. package/dist/crdt/helpers.js.map +1 -0
  74. package/dist/crdt/offline.d.ts +58 -0
  75. package/dist/crdt/offline.d.ts.map +1 -0
  76. package/dist/crdt/offline.js +130 -0
  77. package/dist/crdt/offline.js.map +1 -0
  78. package/dist/crdt/persistence.d.ts +65 -0
  79. package/dist/crdt/persistence.d.ts.map +1 -0
  80. package/dist/crdt/persistence.js +171 -0
  81. package/dist/crdt/persistence.js.map +1 -0
  82. package/dist/crdt/provider.d.ts +109 -0
  83. package/dist/crdt/provider.d.ts.map +1 -0
  84. package/dist/crdt/provider.js +543 -0
  85. package/dist/crdt/provider.js.map +1 -0
  86. package/dist/crdt/store.d.ts +111 -0
  87. package/dist/crdt/store.d.ts.map +1 -0
  88. package/dist/crdt/store.js +158 -0
  89. package/dist/crdt/store.js.map +1 -0
  90. package/dist/crdt/types.d.ts +281 -0
  91. package/dist/crdt/types.d.ts.map +1 -0
  92. package/dist/crdt/types.js +26 -0
  93. package/dist/crdt/types.js.map +1 -0
  94. package/dist/data.d.ts +502 -0
  95. package/dist/data.d.ts.map +1 -0
  96. package/dist/data.js +862 -0
  97. package/dist/data.js.map +1 -0
  98. package/dist/database.d.ts +153 -0
  99. package/dist/database.d.ts.map +1 -0
  100. package/dist/database.js +325 -0
  101. package/dist/database.js.map +1 -0
  102. package/dist/debug.d.ts +87 -0
  103. package/dist/debug.d.ts.map +1 -0
  104. package/dist/debug.js +135 -0
  105. package/dist/debug.js.map +1 -0
  106. package/dist/demo.d.ts +131 -0
  107. package/dist/demo.d.ts.map +1 -0
  108. package/dist/demo.js +168 -0
  109. package/dist/demo.js.map +1 -0
  110. package/dist/deviceId.d.ts +47 -0
  111. package/dist/deviceId.d.ts.map +1 -0
  112. package/dist/deviceId.js +106 -0
  113. package/dist/deviceId.js.map +1 -0
  114. package/dist/diagnostics.d.ts +292 -0
  115. package/dist/diagnostics.d.ts.map +1 -0
  116. package/dist/diagnostics.js +378 -0
  117. package/dist/diagnostics.js.map +1 -0
  118. package/dist/engine.d.ts +230 -0
  119. package/dist/engine.d.ts.map +1 -0
  120. package/dist/engine.js +2636 -0
  121. package/dist/engine.js.map +1 -0
  122. package/dist/entries/actions.d.ts +16 -0
  123. package/dist/entries/actions.d.ts.map +1 -0
  124. package/dist/entries/actions.js +29 -0
  125. package/dist/entries/actions.js.map +1 -0
  126. package/dist/entries/auth.d.ts +19 -0
  127. package/dist/entries/auth.d.ts.map +1 -0
  128. package/dist/entries/auth.js +50 -0
  129. package/dist/entries/auth.js.map +1 -0
  130. package/dist/entries/config.d.ts +15 -0
  131. package/dist/entries/config.d.ts.map +1 -0
  132. package/dist/entries/config.js +20 -0
  133. package/dist/entries/config.js.map +1 -0
  134. package/dist/entries/crdt.d.ts +32 -0
  135. package/dist/entries/crdt.d.ts.map +1 -0
  136. package/dist/entries/crdt.js +52 -0
  137. package/dist/entries/crdt.js.map +1 -0
  138. package/dist/entries/kit.d.ts +22 -0
  139. package/dist/entries/kit.d.ts.map +1 -0
  140. package/dist/entries/kit.js +58 -0
  141. package/dist/entries/kit.js.map +1 -0
  142. package/dist/entries/stores.d.ts +22 -0
  143. package/dist/entries/stores.d.ts.map +1 -0
  144. package/dist/entries/stores.js +57 -0
  145. package/dist/entries/stores.js.map +1 -0
  146. package/dist/entries/types.d.ts +23 -0
  147. package/dist/entries/types.d.ts.map +1 -0
  148. package/dist/entries/types.js +12 -0
  149. package/dist/entries/types.js.map +1 -0
  150. package/dist/entries/utils.d.ts +12 -0
  151. package/dist/entries/utils.d.ts.map +1 -0
  152. package/dist/entries/utils.js +42 -0
  153. package/dist/entries/utils.js.map +1 -0
  154. package/dist/entries/vite.d.ts +20 -0
  155. package/dist/entries/vite.d.ts.map +1 -0
  156. package/dist/entries/vite.js +26 -0
  157. package/dist/entries/vite.js.map +1 -0
  158. package/dist/index.d.ts +77 -0
  159. package/dist/index.d.ts.map +1 -0
  160. package/dist/index.js +234 -0
  161. package/dist/index.js.map +1 -0
  162. package/dist/kit/auth.d.ts +80 -0
  163. package/dist/kit/auth.d.ts.map +1 -0
  164. package/dist/kit/auth.js +75 -0
  165. package/dist/kit/auth.js.map +1 -0
  166. package/dist/kit/confirm.d.ts +111 -0
  167. package/dist/kit/confirm.d.ts.map +1 -0
  168. package/dist/kit/confirm.js +169 -0
  169. package/dist/kit/confirm.js.map +1 -0
  170. package/dist/kit/loads.d.ts +187 -0
  171. package/dist/kit/loads.d.ts.map +1 -0
  172. package/dist/kit/loads.js +208 -0
  173. package/dist/kit/loads.js.map +1 -0
  174. package/dist/kit/server.d.ts +175 -0
  175. package/dist/kit/server.d.ts.map +1 -0
  176. package/dist/kit/server.js +297 -0
  177. package/dist/kit/server.js.map +1 -0
  178. package/dist/kit/sw.d.ts +176 -0
  179. package/dist/kit/sw.d.ts.map +1 -0
  180. package/dist/kit/sw.js +320 -0
  181. package/dist/kit/sw.js.map +1 -0
  182. package/dist/queue.d.ts +306 -0
  183. package/dist/queue.d.ts.map +1 -0
  184. package/dist/queue.js +925 -0
  185. package/dist/queue.js.map +1 -0
  186. package/dist/realtime.d.ts +280 -0
  187. package/dist/realtime.d.ts.map +1 -0
  188. package/dist/realtime.js +1031 -0
  189. package/dist/realtime.js.map +1 -0
  190. package/dist/runtime/runtimeConfig.d.ts +110 -0
  191. package/dist/runtime/runtimeConfig.d.ts.map +1 -0
  192. package/dist/runtime/runtimeConfig.js +260 -0
  193. package/dist/runtime/runtimeConfig.js.map +1 -0
  194. package/dist/schema.d.ts +150 -0
  195. package/dist/schema.d.ts.map +1 -0
  196. package/dist/schema.js +891 -0
  197. package/dist/schema.js.map +1 -0
  198. package/dist/stores/authState.d.ts +204 -0
  199. package/dist/stores/authState.d.ts.map +1 -0
  200. package/dist/stores/authState.js +336 -0
  201. package/dist/stores/authState.js.map +1 -0
  202. package/dist/stores/factories.d.ts +140 -0
  203. package/dist/stores/factories.d.ts.map +1 -0
  204. package/dist/stores/factories.js +157 -0
  205. package/dist/stores/factories.js.map +1 -0
  206. package/dist/stores/network.d.ts +48 -0
  207. package/dist/stores/network.d.ts.map +1 -0
  208. package/dist/stores/network.js +261 -0
  209. package/dist/stores/network.js.map +1 -0
  210. package/dist/stores/remoteChanges.d.ts +417 -0
  211. package/dist/stores/remoteChanges.d.ts.map +1 -0
  212. package/dist/stores/remoteChanges.js +626 -0
  213. package/dist/stores/remoteChanges.js.map +1 -0
  214. package/dist/stores/sync.d.ts +165 -0
  215. package/dist/stores/sync.d.ts.map +1 -0
  216. package/dist/stores/sync.js +275 -0
  217. package/dist/stores/sync.js.map +1 -0
  218. package/dist/supabase/auth.d.ts +219 -0
  219. package/dist/supabase/auth.d.ts.map +1 -0
  220. package/dist/supabase/auth.js +459 -0
  221. package/dist/supabase/auth.js.map +1 -0
  222. package/dist/supabase/client.d.ts +88 -0
  223. package/dist/supabase/client.d.ts.map +1 -0
  224. package/dist/supabase/client.js +313 -0
  225. package/dist/supabase/client.js.map +1 -0
  226. package/dist/supabase/validate.d.ts +118 -0
  227. package/dist/supabase/validate.d.ts.map +1 -0
  228. package/dist/supabase/validate.js +208 -0
  229. package/dist/supabase/validate.js.map +1 -0
  230. package/dist/sw/build/vite-plugin.d.ts +149 -0
  231. package/dist/sw/build/vite-plugin.d.ts.map +1 -0
  232. package/dist/sw/build/vite-plugin.js +517 -0
  233. package/dist/sw/build/vite-plugin.js.map +1 -0
  234. package/dist/sw/sw.js +664 -0
  235. package/dist/types.d.ts +363 -0
  236. package/dist/types.d.ts.map +1 -0
  237. package/dist/types.js +18 -0
  238. package/dist/types.js.map +1 -0
  239. package/dist/utils.d.ts +85 -0
  240. package/dist/utils.d.ts.map +1 -0
  241. package/dist/utils.js +156 -0
  242. package/dist/utils.js.map +1 -0
  243. package/package.json +117 -0
  244. package/src/components/DeferredChangesBanner.svelte +477 -0
  245. package/src/components/DemoBanner.svelte +110 -0
  246. package/src/components/SyncStatus.svelte +1732 -0
@@ -0,0 +1,204 @@
1
+ /**
2
+ * @fileoverview Remote Change Animation Action
3
+ *
4
+ * A Svelte action that automatically adds remote change animations to elements.
5
+ * Use this on list items, cards, or any element that can be updated remotely
6
+ * (e.g., via Supabase Realtime subscriptions).
7
+ *
8
+ * The action detects the ACTION TYPE from the remote change and applies
9
+ * the appropriate CSS animation class:
10
+ * - `'create'` --> `item-created` (slide in with burst)
11
+ * - `'delete'` --> `item-deleting` (slide out with fade)
12
+ * - `'toggle'` --> `item-toggled` (+ checkbox-animating + completion-ripple)
13
+ * - `'increment'` --> `counter-increment` (bump up)
14
+ * - `'decrement'` --> `counter-decrement` (bump down)
15
+ * - `'reorder'` --> `item-reordering` (slide to new position)
16
+ * - `'rename'` --> `text-changed` (highlight flash)
17
+ * - `'update'` --> `item-changed` (default highlight)
18
+ *
19
+ * @example
20
+ * ```svelte
21
+ * <div use:remoteChangeAnimation={{ entityId: item.id, entityType: 'goals' }}>
22
+ * ...
23
+ * </div>
24
+ * ```
25
+ *
26
+ * @see {@link remoteChangeAnimation} for the main Svelte action
27
+ * @see {@link trackEditing} for deferred-change tracking on forms
28
+ * @see {@link triggerLocalAnimation} for programmatic local animations
29
+ */
30
+ import { type RemoteActionType } from '../stores/remoteChanges';
31
+ /**
32
+ * Configuration options for the {@link remoteChangeAnimation} Svelte action.
33
+ */
34
+ interface RemoteChangeOptions {
35
+ /** The unique identifier of the entity being watched (e.g., a row UUID). */
36
+ entityId: string;
37
+ /** The entity type / table name (e.g., `'goals'`, `'tasks'`). */
38
+ entityType: string;
39
+ /**
40
+ * Optional list of field names to watch. When provided, animations are
41
+ * only triggered if the remote change includes at least one of these
42
+ * fields (or the wildcard `'*'`). Omit to animate on any field change.
43
+ */
44
+ fields?: string[];
45
+ /**
46
+ * Optional CSS class override. When set, this class is used instead of
47
+ * the default mapping from {@link ACTION_ANIMATION_MAP}.
48
+ */
49
+ animationClass?: string;
50
+ /**
51
+ * Optional callback invoked when a remote action is detected.
52
+ * Useful for component-specific handling beyond CSS animations
53
+ * (e.g., updating local state, playing sounds, showing toasts).
54
+ *
55
+ * @param actionType - The type of remote action detected.
56
+ * @param fields - The list of fields that changed.
57
+ */
58
+ onAction?: (actionType: RemoteActionType, fields: string[]) => void;
59
+ }
60
+ /**
61
+ * Svelte action that watches for remote changes on a specific entity and
62
+ * applies the appropriate CSS animation class to the host element.
63
+ *
64
+ * **Lifecycle:**
65
+ * 1. On mount, checks for a recent change that may have arrived before
66
+ * the element was rendered (important for CREATE animations on new items).
67
+ * 2. Subscribes to the `remoteChangesStore` for future changes.
68
+ * 3. Subscribes to a pending-delete indicator for delete animations.
69
+ * 4. On update, re-subscribes if the entity identity changes.
70
+ * 5. On destroy, unsubscribes and cleans up CSS classes.
71
+ *
72
+ * @param node - The DOM element to animate.
73
+ * @param options - Configuration specifying which entity to watch.
74
+ * @returns A Svelte action lifecycle object with `update` and `destroy` methods.
75
+ *
76
+ * @example
77
+ * ```svelte
78
+ * <div use:remoteChangeAnimation={{ entityId: item.id, entityType: 'goals' }}>
79
+ * {item.name}
80
+ * </div>
81
+ * ```
82
+ */
83
+ export declare function remoteChangeAnimation(node: HTMLElement, options: RemoteChangeOptions): {
84
+ /**
85
+ * Called when the action's options change. If the entity identity
86
+ * (`entityId` or `entityType`) has changed, tears down old subscriptions
87
+ * and creates new ones for the updated entity.
88
+ *
89
+ * @param newOptions - The updated {@link RemoteChangeOptions}.
90
+ */
91
+ update(newOptions: RemoteChangeOptions): void;
92
+ /**
93
+ * Cleanup handler — unsubscribes from all stores, removes the base
94
+ * CSS class, and clears the element from the animation tracking set.
95
+ */
96
+ destroy(): void;
97
+ };
98
+ /**
99
+ * Svelte action for form elements that should track editing state.
100
+ * Use this on modal forms with Save buttons to defer remote changes
101
+ * while the user is actively editing, preventing disruptive overwrites.
102
+ *
103
+ * When the form is destroyed (e.g., modal closes), any deferred changes
104
+ * are passed to the `onDeferredChanges` callback so the component can
105
+ * decide how to reconcile them.
106
+ *
107
+ * @example
108
+ * ```svelte
109
+ * <form use:trackEditing={{ entityId: item.id, entityType: 'goals', formType: 'manual-save' }}>
110
+ * ...
111
+ * </form>
112
+ * ```
113
+ */
114
+ /**
115
+ * Configuration options for the {@link trackEditing} Svelte action.
116
+ */
117
+ interface TrackEditingOptions {
118
+ /** The unique identifier of the entity being edited. */
119
+ entityId: string;
120
+ /** The entity type / table name (e.g., `'goals'`, `'tasks'`). */
121
+ entityType: string;
122
+ /**
123
+ * The save behaviour of the form:
124
+ * - `'auto-save'` — changes are saved immediately (e.g., inline editing).
125
+ * - `'manual-save'` — changes are saved on explicit submit (e.g., modal form).
126
+ */
127
+ formType: 'auto-save' | 'manual-save';
128
+ /**
129
+ * Optional list of field names this form edits. When provided, only
130
+ * remote changes to these fields are deferred; changes to other fields
131
+ * are applied immediately.
132
+ */
133
+ fields?: string[];
134
+ /**
135
+ * Callback invoked when the form closes and there are deferred changes
136
+ * that need processing (e.g., conflict resolution, data refresh).
137
+ *
138
+ * @param changes - The array of deferred remote change objects.
139
+ */
140
+ onDeferredChanges?: (changes: unknown[]) => void;
141
+ }
142
+ /**
143
+ * Svelte action that marks an entity as "being edited" in the remote changes
144
+ * store. While editing, incoming remote changes for the same entity are
145
+ * deferred instead of applied immediately.
146
+ *
147
+ * **Lifecycle:**
148
+ * 1. On mount, calls `remoteChangesStore.startEditing()` to begin deferral.
149
+ * 2. Periodically checks for deferred changes and toggles a CSS class
150
+ * (`has-deferred-changes`) on the node for visual indication.
151
+ * 3. On update, re-registers if the entity identity changes.
152
+ * 4. On destroy, calls `remoteChangesStore.stopEditing()` and invokes
153
+ * `onDeferredChanges` if any changes were deferred.
154
+ *
155
+ * @param node - The form DOM element.
156
+ * @param options - Configuration specifying which entity is being edited.
157
+ * @returns A Svelte action lifecycle object with `update` and `destroy` methods.
158
+ */
159
+ export declare function trackEditing(node: HTMLElement, options: TrackEditingOptions): {
160
+ /**
161
+ * Called when the action's options change. If the entity identity
162
+ * changes, stops tracking the old entity and starts tracking the new one.
163
+ *
164
+ * @param newOptions - The updated {@link TrackEditingOptions}.
165
+ */
166
+ update(newOptions: TrackEditingOptions): void;
167
+ /**
168
+ * Cleanup handler — stops the polling interval, removes CSS classes,
169
+ * stops editing in the store, and notifies the callback of any
170
+ * deferred changes that accumulated during the editing session.
171
+ */
172
+ destroy(): void;
173
+ };
174
+ /**
175
+ * Trigger a local action animation on an element.
176
+ *
177
+ * Use this to make local user actions (e.g., tapping a checkbox, incrementing
178
+ * a counter) animate with the same visual treatment as remote changes, giving
179
+ * the UI a consistent feel.
180
+ *
181
+ * For `increment` and `decrement` actions, rapid repeated invocations will
182
+ * restart the animation instead of being blocked — this allows the counter
183
+ * to visually "bump" on each tap.
184
+ *
185
+ * @param element - The DOM element to animate (or `null`, in which case this is a no-op).
186
+ * @param actionType - The type of animation to apply.
187
+ *
188
+ * @example
189
+ * ```svelte
190
+ * <script>
191
+ * import { triggerLocalAnimation } from 'stellar-drive';
192
+ * let element: HTMLElement;
193
+ *
194
+ * function handleToggle() {
195
+ * triggerLocalAnimation(element, 'toggle');
196
+ * onToggle?.();
197
+ * }
198
+ * </script>
199
+ * <div bind:this={element}>...</div>
200
+ * ```
201
+ */
202
+ export declare function triggerLocalAnimation(element: HTMLElement | null, actionType: RemoteActionType): void;
203
+ export {};
204
+ //# sourceMappingURL=remoteChange.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remoteChange.d.ts","sourceRoot":"","sources":["../../src/actions/remoteChange.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,EAIL,KAAK,gBAAgB,EACtB,MAAM,yBAAyB,CAAC;AAMjC;;GAEG;AACH,UAAU,mBAAmB;IAC3B,4EAA4E;IAC5E,QAAQ,EAAE,MAAM,CAAC;IAEjB,iEAAiE;IACjE,UAAU,EAAE,MAAM,CAAC;IAEnB;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAElB;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;;;;;;OAOG;IACH,QAAQ,CAAC,EAAE,CAAC,UAAU,EAAE,gBAAgB,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;CACrE;AAsDD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,mBAAmB;IAgJjF;;;;;;OAMG;uBACgB,mBAAmB;IA4BtC;;;OAGG;;EAQN;AAMD;;;;;;;;;;;;;;;GAeG;AAEH;;GAEG;AACH,UAAU,mBAAmB;IAC3B,wDAAwD;IACxD,QAAQ,EAAE,MAAM,CAAC;IAEjB,iEAAiE;IACjE,UAAU,EAAE,MAAM,CAAC;IAEnB;;;;OAIG;IACH,QAAQ,EAAE,WAAW,GAAG,aAAa,CAAC;IAEtC;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAElB;;;;;OAKG;IACH,iBAAiB,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;CAClD;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,mBAAmB;IAwBxE;;;;;OAKG;uBACgB,mBAAmB;IAatC;;;;OAIG;;EAcN;AAMD;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,WAAW,GAAG,IAAI,EAC3B,UAAU,EAAE,gBAAgB,GAC3B,IAAI,CA8DN"}
@@ -0,0 +1,424 @@
1
+ /**
2
+ * @fileoverview Remote Change Animation Action
3
+ *
4
+ * A Svelte action that automatically adds remote change animations to elements.
5
+ * Use this on list items, cards, or any element that can be updated remotely
6
+ * (e.g., via Supabase Realtime subscriptions).
7
+ *
8
+ * The action detects the ACTION TYPE from the remote change and applies
9
+ * the appropriate CSS animation class:
10
+ * - `'create'` --> `item-created` (slide in with burst)
11
+ * - `'delete'` --> `item-deleting` (slide out with fade)
12
+ * - `'toggle'` --> `item-toggled` (+ checkbox-animating + completion-ripple)
13
+ * - `'increment'` --> `counter-increment` (bump up)
14
+ * - `'decrement'` --> `counter-decrement` (bump down)
15
+ * - `'reorder'` --> `item-reordering` (slide to new position)
16
+ * - `'rename'` --> `text-changed` (highlight flash)
17
+ * - `'update'` --> `item-changed` (default highlight)
18
+ *
19
+ * @example
20
+ * ```svelte
21
+ * <div use:remoteChangeAnimation={{ entityId: item.id, entityType: 'goals' }}>
22
+ * ...
23
+ * </div>
24
+ * ```
25
+ *
26
+ * @see {@link remoteChangeAnimation} for the main Svelte action
27
+ * @see {@link trackEditing} for deferred-change tracking on forms
28
+ * @see {@link triggerLocalAnimation} for programmatic local animations
29
+ */
30
+ import { remoteChangesStore, createRecentChangeIndicator, createPendingDeleteIndicator } from '../stores/remoteChanges';
31
+ // =============================================================================
32
+ // ACTION-TO-CSS ANIMATION MAPPING
33
+ // =============================================================================
34
+ /**
35
+ * Maps each {@link RemoteActionType} to the CSS class name that triggers
36
+ * the corresponding animation. The consuming app must define these CSS
37
+ * classes (keyframes + durations) in its stylesheet.
38
+ */
39
+ const ACTION_ANIMATION_MAP = {
40
+ create: 'item-created',
41
+ delete: 'item-deleting',
42
+ toggle: 'item-toggled',
43
+ increment: 'counter-increment',
44
+ decrement: 'counter-decrement',
45
+ reorder: 'item-reordering',
46
+ rename: 'text-changed',
47
+ update: 'item-changed'
48
+ };
49
+ /**
50
+ * Maps each {@link RemoteActionType} to its animation duration in
51
+ * milliseconds. Used for fallback cleanup timers in case the
52
+ * `animationend` DOM event never fires (e.g., display:none elements).
53
+ */
54
+ const ACTION_DURATION_MAP = {
55
+ create: 600,
56
+ delete: 500,
57
+ toggle: 600,
58
+ increment: 400,
59
+ decrement: 400,
60
+ reorder: 400,
61
+ rename: 700,
62
+ update: 1600
63
+ };
64
+ // =============================================================================
65
+ // ANIMATION OVERLAP PREVENTION
66
+ // =============================================================================
67
+ /**
68
+ * Tracks elements that currently have an active animation. Prevents
69
+ * overlapping animations on the same element which would cause visual
70
+ * glitches. Uses `WeakSet` so entries are automatically garbage-collected
71
+ * when the element is removed from the DOM.
72
+ */
73
+ const animatingElements = new WeakSet();
74
+ // =============================================================================
75
+ // SVELTE ACTION: remoteChangeAnimation
76
+ // =============================================================================
77
+ /**
78
+ * Svelte action that watches for remote changes on a specific entity and
79
+ * applies the appropriate CSS animation class to the host element.
80
+ *
81
+ * **Lifecycle:**
82
+ * 1. On mount, checks for a recent change that may have arrived before
83
+ * the element was rendered (important for CREATE animations on new items).
84
+ * 2. Subscribes to the `remoteChangesStore` for future changes.
85
+ * 3. Subscribes to a pending-delete indicator for delete animations.
86
+ * 4. On update, re-subscribes if the entity identity changes.
87
+ * 5. On destroy, unsubscribes and cleans up CSS classes.
88
+ *
89
+ * @param node - The DOM element to animate.
90
+ * @param options - Configuration specifying which entity to watch.
91
+ * @returns A Svelte action lifecycle object with `update` and `destroy` methods.
92
+ *
93
+ * @example
94
+ * ```svelte
95
+ * <div use:remoteChangeAnimation={{ entityId: item.id, entityType: 'goals' }}>
96
+ * {item.name}
97
+ * </div>
98
+ * ```
99
+ */
100
+ export function remoteChangeAnimation(node, options) {
101
+ let { entityId, entityType, fields, animationClass, onAction } = options;
102
+ /* Add base class for styling hooks (e.g., transition defaults) */
103
+ node.classList.add('syncable-item');
104
+ // ---------------------------------------------------------------------------
105
+ // ANIMATION APPLICATION LOGIC
106
+ // ---------------------------------------------------------------------------
107
+ /**
108
+ * Apply the appropriate CSS animation to the node based on the change's
109
+ * action type and affected fields.
110
+ *
111
+ * Handles special cases for toggle (checkbox + ripple), increment/decrement
112
+ * (counter sub-element), and delete (no class removal — element will be
113
+ * removed from DOM by the parent component).
114
+ *
115
+ * @param change - The remote change descriptor with `actionType` and `fields`.
116
+ */
117
+ function applyAnimation(change) {
118
+ /* If specific fields are configured, only animate if at least one matches */
119
+ if (fields && fields.length > 0) {
120
+ const fieldsList = fields; /* Capture for closure safety */
121
+ const hasRelevantChange = change.fields.some((f) => f === '*' || fieldsList.includes(f));
122
+ if (!hasRelevantChange)
123
+ return;
124
+ }
125
+ /* Prevent overlapping animations on the same element */
126
+ if (animatingElements.has(node))
127
+ return;
128
+ animatingElements.add(node);
129
+ /* Determine animation class based on action type */
130
+ const actionType = change.actionType;
131
+ const cssClass = animationClass || ACTION_ANIMATION_MAP[actionType] || 'item-changed';
132
+ const duration = ACTION_DURATION_MAP[actionType] || 1600;
133
+ /* Call action callback if provided (for component-specific handling) */
134
+ if (onAction) {
135
+ onAction(actionType, change.fields);
136
+ }
137
+ /* Apply animation class */
138
+ node.classList.add(cssClass);
139
+ /* For toggle actions, also add checkbox animation to child checkbox elements */
140
+ if (actionType === 'toggle') {
141
+ const checkbox = node.querySelector('.checkbox, [class*="checkbox"]');
142
+ if (checkbox) {
143
+ checkbox.classList.add('checkbox-animating');
144
+ setTimeout(() => checkbox.classList.remove('checkbox-animating'), 500);
145
+ }
146
+ /* Add completion ripple effect — a temporary <span> that auto-removes */
147
+ const ripple = document.createElement('span');
148
+ ripple.className = 'completion-ripple';
149
+ node.appendChild(ripple);
150
+ setTimeout(() => ripple.remove(), 700);
151
+ }
152
+ /* For increment/decrement, animate the counter sub-element specifically */
153
+ if (actionType === 'increment' || actionType === 'decrement') {
154
+ const counter = node.querySelector('[class*="value"], [class*="counter"], [class*="current"]');
155
+ if (counter) {
156
+ counter.classList.add(cssClass);
157
+ setTimeout(() => counter.classList.remove(cssClass), duration);
158
+ }
159
+ }
160
+ /* For delete animations, don't remove the class — the element will be
161
+ * removed from DOM after the animation. Removing it early causes the item
162
+ * to briefly reappear between animation end and DOM removal. */
163
+ if (actionType === 'delete')
164
+ return;
165
+ /* Remove class after animation completes */
166
+ const handleAnimationEnd = () => {
167
+ node.classList.remove(cssClass);
168
+ animatingElements.delete(node);
169
+ node.removeEventListener('animationend', handleAnimationEnd);
170
+ };
171
+ node.addEventListener('animationend', handleAnimationEnd);
172
+ /* Fallback removal in case animationend doesn't fire
173
+ * (e.g., element is display:none or animation is interrupted) */
174
+ setTimeout(() => {
175
+ node.classList.remove(cssClass);
176
+ animatingElements.delete(node);
177
+ }, duration + 100);
178
+ }
179
+ // ---------------------------------------------------------------------------
180
+ // INITIAL CHECK (HANDLES CREATE-ON-MOUNT SCENARIO)
181
+ // ---------------------------------------------------------------------------
182
+ /* Check for a recent change immediately on mount. This handles the case
183
+ * where the element mounts after a remote INSERT — the store already has
184
+ * the change recorded, and we need to animate the newly-rendered item. */
185
+ const initialChange = remoteChangesStore.getRecentChange(entityId, entityType);
186
+ if (initialChange) {
187
+ /* Use requestAnimationFrame to ensure DOM is fully ready */
188
+ requestAnimationFrame(() => {
189
+ applyAnimation(initialChange);
190
+ });
191
+ }
192
+ // ---------------------------------------------------------------------------
193
+ // STORE SUBSCRIPTIONS
194
+ // ---------------------------------------------------------------------------
195
+ /* Create derived stores to watch for future changes and pending deletes */
196
+ let changeIndicator = createRecentChangeIndicator(entityId, entityType);
197
+ let deleteIndicator = createPendingDeleteIndicator(entityId, entityType);
198
+ /* Track the current unsubscribe functions */
199
+ let unsubscribeChange = changeIndicator.subscribe((change) => {
200
+ /* Skip if no change or if this is the same change we already animated on mount */
201
+ if (!change)
202
+ return;
203
+ if (initialChange && change.timestamp === initialChange.timestamp)
204
+ return;
205
+ applyAnimation(change);
206
+ });
207
+ /* Watch for pending deletes to apply delete animation */
208
+ let unsubscribeDelete = deleteIndicator.subscribe((isPendingDelete) => {
209
+ if (isPendingDelete) {
210
+ /* Apply delete animation immediately */
211
+ const deleteClass = ACTION_ANIMATION_MAP['delete'];
212
+ node.classList.add(deleteClass);
213
+ /* Call action callback if provided */
214
+ if (onAction) {
215
+ onAction('delete', ['*']);
216
+ }
217
+ }
218
+ });
219
+ // ---------------------------------------------------------------------------
220
+ // SVELTE ACTION LIFECYCLE
221
+ // ---------------------------------------------------------------------------
222
+ return {
223
+ /**
224
+ * Called when the action's options change. If the entity identity
225
+ * (`entityId` or `entityType`) has changed, tears down old subscriptions
226
+ * and creates new ones for the updated entity.
227
+ *
228
+ * @param newOptions - The updated {@link RemoteChangeOptions}.
229
+ */
230
+ update(newOptions) {
231
+ /* If entity changed, re-subscribe with new entity */
232
+ if (newOptions.entityId !== entityId || newOptions.entityType !== entityType) {
233
+ unsubscribeChange();
234
+ unsubscribeDelete();
235
+ entityId = newOptions.entityId;
236
+ entityType = newOptions.entityType;
237
+ fields = newOptions.fields;
238
+ animationClass = newOptions.animationClass;
239
+ onAction = newOptions.onAction;
240
+ changeIndicator = createRecentChangeIndicator(entityId, entityType);
241
+ deleteIndicator = createPendingDeleteIndicator(entityId, entityType);
242
+ unsubscribeChange = changeIndicator.subscribe((change) => {
243
+ if (!change)
244
+ return;
245
+ applyAnimation(change);
246
+ });
247
+ unsubscribeDelete = deleteIndicator.subscribe((isPendingDelete) => {
248
+ if (isPendingDelete) {
249
+ const deleteClass = ACTION_ANIMATION_MAP['delete'];
250
+ node.classList.add(deleteClass);
251
+ if (onAction) {
252
+ onAction('delete', ['*']);
253
+ }
254
+ }
255
+ });
256
+ }
257
+ },
258
+ /**
259
+ * Cleanup handler — unsubscribes from all stores, removes the base
260
+ * CSS class, and clears the element from the animation tracking set.
261
+ */
262
+ destroy() {
263
+ unsubscribeChange();
264
+ unsubscribeDelete();
265
+ node.classList.remove('syncable-item');
266
+ animatingElements.delete(node);
267
+ }
268
+ };
269
+ }
270
+ /**
271
+ * Svelte action that marks an entity as "being edited" in the remote changes
272
+ * store. While editing, incoming remote changes for the same entity are
273
+ * deferred instead of applied immediately.
274
+ *
275
+ * **Lifecycle:**
276
+ * 1. On mount, calls `remoteChangesStore.startEditing()` to begin deferral.
277
+ * 2. Periodically checks for deferred changes and toggles a CSS class
278
+ * (`has-deferred-changes`) on the node for visual indication.
279
+ * 3. On update, re-registers if the entity identity changes.
280
+ * 4. On destroy, calls `remoteChangesStore.stopEditing()` and invokes
281
+ * `onDeferredChanges` if any changes were deferred.
282
+ *
283
+ * @param node - The form DOM element.
284
+ * @param options - Configuration specifying which entity is being edited.
285
+ * @returns A Svelte action lifecycle object with `update` and `destroy` methods.
286
+ */
287
+ export function trackEditing(node, options) {
288
+ const { entityId, entityType, formType, fields, onDeferredChanges } = options;
289
+ /* Start tracking when the element mounts */
290
+ remoteChangesStore.startEditing(entityId, entityType, formType, fields);
291
+ /**
292
+ * Update the `has-deferred-changes` CSS class based on whether
293
+ * remote changes have been deferred for this entity.
294
+ */
295
+ const updateDeferredIndicator = () => {
296
+ const hasDeferred = remoteChangesStore.hasDeferredChanges(entityId, entityType);
297
+ if (hasDeferred) {
298
+ node.classList.add('has-deferred-changes');
299
+ }
300
+ else {
301
+ node.classList.remove('has-deferred-changes');
302
+ }
303
+ };
304
+ /* Check periodically for deferred changes (1-second polling interval) */
305
+ const interval = setInterval(updateDeferredIndicator, 1000);
306
+ updateDeferredIndicator();
307
+ return {
308
+ /**
309
+ * Called when the action's options change. If the entity identity
310
+ * changes, stops tracking the old entity and starts tracking the new one.
311
+ *
312
+ * @param newOptions - The updated {@link TrackEditingOptions}.
313
+ */
314
+ update(newOptions) {
315
+ /* If entity changed, stop old tracking and start new */
316
+ if (newOptions.entityId !== entityId || newOptions.entityType !== entityType) {
317
+ remoteChangesStore.stopEditing(entityId, entityType);
318
+ remoteChangesStore.startEditing(newOptions.entityId, newOptions.entityType, newOptions.formType, newOptions.fields);
319
+ }
320
+ },
321
+ /**
322
+ * Cleanup handler — stops the polling interval, removes CSS classes,
323
+ * stops editing in the store, and notifies the callback of any
324
+ * deferred changes that accumulated during the editing session.
325
+ */
326
+ destroy() {
327
+ clearInterval(interval);
328
+ node.classList.remove('has-deferred-changes');
329
+ /* Stop tracking and get any deferred changes */
330
+ const deferredChanges = remoteChangesStore.stopEditing(entityId, entityType);
331
+ /* Notify callback if there are deferred changes */
332
+ if (deferredChanges.length > 0 && onDeferredChanges) {
333
+ onDeferredChanges(deferredChanges);
334
+ }
335
+ }
336
+ };
337
+ }
338
+ // =============================================================================
339
+ // PROGRAMMATIC LOCAL ANIMATION TRIGGER
340
+ // =============================================================================
341
+ /**
342
+ * Trigger a local action animation on an element.
343
+ *
344
+ * Use this to make local user actions (e.g., tapping a checkbox, incrementing
345
+ * a counter) animate with the same visual treatment as remote changes, giving
346
+ * the UI a consistent feel.
347
+ *
348
+ * For `increment` and `decrement` actions, rapid repeated invocations will
349
+ * restart the animation instead of being blocked — this allows the counter
350
+ * to visually "bump" on each tap.
351
+ *
352
+ * @param element - The DOM element to animate (or `null`, in which case this is a no-op).
353
+ * @param actionType - The type of animation to apply.
354
+ *
355
+ * @example
356
+ * ```svelte
357
+ * <script>
358
+ * import { triggerLocalAnimation } from 'stellar-drive';
359
+ * let element: HTMLElement;
360
+ *
361
+ * function handleToggle() {
362
+ * triggerLocalAnimation(element, 'toggle');
363
+ * onToggle?.();
364
+ * }
365
+ * </script>
366
+ * <div bind:this={element}>...</div>
367
+ * ```
368
+ */
369
+ export function triggerLocalAnimation(element, actionType) {
370
+ if (!element)
371
+ return;
372
+ const cssClass = ACTION_ANIMATION_MAP[actionType] || 'item-changed';
373
+ const duration = ACTION_DURATION_MAP[actionType] || 1600;
374
+ /* For increment/decrement, restart animation on rapid taps instead of blocking */
375
+ if (actionType === 'increment' || actionType === 'decrement') {
376
+ if (animatingElements.has(element)) {
377
+ /* Force restart: remove class, trigger reflow via offsetWidth read, re-add */
378
+ element.classList.remove(cssClass);
379
+ void element.offsetWidth;
380
+ }
381
+ }
382
+ else {
383
+ /* Prevent overlapping animations for other types */
384
+ if (animatingElements.has(element))
385
+ return;
386
+ }
387
+ animatingElements.add(element);
388
+ /* Apply animation class */
389
+ element.classList.add(cssClass);
390
+ /* For toggle actions, also animate checkbox elements */
391
+ if (actionType === 'toggle') {
392
+ const checkbox = element.querySelector('.checkbox, [class*="checkbox"]');
393
+ if (checkbox) {
394
+ checkbox.classList.add('checkbox-animating');
395
+ setTimeout(() => checkbox.classList.remove('checkbox-animating'), 500);
396
+ }
397
+ /* Add completion ripple effect */
398
+ const ripple = document.createElement('span');
399
+ ripple.className = 'completion-ripple';
400
+ element.appendChild(ripple);
401
+ setTimeout(() => ripple.remove(), 700);
402
+ }
403
+ /* For increment/decrement, animate the counter sub-element specifically */
404
+ if (actionType === 'increment' || actionType === 'decrement') {
405
+ const counter = element.querySelector('[class*="value"], [class*="counter"], [class*="current"]');
406
+ if (counter) {
407
+ counter.classList.add(cssClass);
408
+ setTimeout(() => counter.classList.remove(cssClass), duration);
409
+ }
410
+ }
411
+ /* Remove class after animation completes */
412
+ const handleAnimationEnd = () => {
413
+ element.classList.remove(cssClass);
414
+ animatingElements.delete(element);
415
+ element.removeEventListener('animationend', handleAnimationEnd);
416
+ };
417
+ element.addEventListener('animationend', handleAnimationEnd);
418
+ /* Fallback removal in case animationend doesn't fire */
419
+ setTimeout(() => {
420
+ element.classList.remove(cssClass);
421
+ animatingElements.delete(element);
422
+ }, duration + 100);
423
+ }
424
+ //# sourceMappingURL=remoteChange.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remoteChange.js","sourceRoot":"","sources":["../../src/actions/remoteChange.ts"],"names":[],"mappings":"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"}