@tribepad/themis 1.5.6 → 1.5.8

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tribepad/themis",
3
- "version": "1.5.6",
3
+ "version": "1.5.8",
4
4
  "description": "Accessible React component library built on React Aria primitives",
5
5
  "author": "Tribepad <mbasford@tribepad.com>",
6
6
  "license": "MIT",
@@ -283,3 +283,98 @@ function RTLHarness(): ReactElement {
283
283
  export const RTL: Story = {
284
284
  render: () => <RTLHarness />,
285
285
  };
286
+
287
+ // ─────────────────────────────────────────────────────────────────────────────
288
+ // preserveState — Activity-backed step state survival
289
+ // ─────────────────────────────────────────────────────────────────────────────
290
+
291
+ /**
292
+ * Tiny step body with its own local state, so we can observe whether state
293
+ * survives a step transition. A counter + a textarea: both reset to their
294
+ * initial values whenever the component re-mounts. With `preserveState`,
295
+ * the component stays mounted (just hidden) and the values persist.
296
+ */
297
+ function CounterStep({ label }: { label: string }): ReactElement {
298
+ const [count, setCount] = useState(0);
299
+ const [draft, setDraft] = useState('');
300
+ return (
301
+ <div className="flex flex-col gap-3">
302
+ <p className="text-sm text-[var(--menu-muted)]">
303
+ Try editing the textarea and bumping the counter, then move to the next
304
+ step and back. With <code>preserveState</code> ON your values stay; OFF,
305
+ they reset on every return.
306
+ </p>
307
+ <label className="flex flex-col gap-1 text-sm">
308
+ <span className="font-medium">{label} — draft</span>
309
+ <textarea
310
+ rows={3}
311
+ value={draft}
312
+ onChange={(e): void => setDraft(e.target.value)}
313
+ className="rounded-md border border-[var(--border)] bg-[var(--background)] p-2 text-sm"
314
+ />
315
+ </label>
316
+ <div className="flex items-center gap-2 text-sm">
317
+ <span className="font-medium">Count:</span>
318
+ <span className="font-mono">{count}</span>
319
+ <button
320
+ type="button"
321
+ onClick={(): void => setCount((c) => c + 1)}
322
+ className="rounded-md border border-[var(--border)] px-2 py-1 text-xs"
323
+ >
324
+ +1
325
+ </button>
326
+ </div>
327
+ </div>
328
+ );
329
+ }
330
+
331
+ function PreserveStateHarness({ preserveState }: { preserveState: boolean }): ReactElement {
332
+ const [step, setStep] = useState(0);
333
+ const subset = STEPS.slice(0, 3);
334
+ return (
335
+ <div className="h-screen p-6">
336
+ <p className="mb-3 text-sm">
337
+ <span className="font-medium">preserveState:</span>{' '}
338
+ <span className="font-mono">{String(preserveState)}</span>
339
+ </p>
340
+ <Wizard
341
+ currentStep={step}
342
+ steps={subset}
343
+ onStepChange={(ev): void => setStep(ev.index)}
344
+ >
345
+ <Wizard.Content preserveState={preserveState}>
346
+ {subset.map((s) => (
347
+ <Wizard.Step key={s.id} id={s.id}>
348
+ <CounterStep label={s.label} />
349
+ </Wizard.Step>
350
+ ))}
351
+ </Wizard.Content>
352
+ <Wizard.Navigation labels={{ back: 'Back', next: 'Next' }} />
353
+ </Wizard>
354
+ </div>
355
+ );
356
+ }
357
+
358
+ export const PreserveState: Story = {
359
+ parameters: {
360
+ docs: {
361
+ description: {
362
+ story:
363
+ 'Demonstrates `Wizard.Content preserveState`. Type in the textarea + click `+1`, advance to the next step, then click Back. With `preserveState` ON the values are still there (every step stays mounted, wrapped in `<Activity mode="hidden">`); with OFF the step subtree is unmounted on every transition and the local state is destroyed on remount.',
364
+ },
365
+ },
366
+ },
367
+ render: () => <PreserveStateHarness preserveState={true} />,
368
+ };
369
+
370
+ export const PreserveStateOff: Story = {
371
+ parameters: {
372
+ docs: {
373
+ description: {
374
+ story:
375
+ 'Legacy default for comparison — `preserveState={false}`. Same harness, no preservation: the counter + textarea reset every time you navigate away from a step. This is the pre-1.5.8 behaviour, still the default for backward compatibility and for wizards with heavy per-step initialisation.',
376
+ },
377
+ },
378
+ },
379
+ render: () => <PreserveStateHarness preserveState={false} />,
380
+ };