@picked/svelte 0.0.1-dev.1793776638554 → 0.0.1-dev.1793923852884

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 (50) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/experience/set-picked-context.js +1 -1
  3. package/dist/plugins/devtools/DevToolsExperience.svelte +155 -80
  4. package/dist/plugins/devtools/customTools.d.ts +2 -2
  5. package/dist/plugins/devtools/derive/answer-display/answer-display.d.ts +14 -0
  6. package/dist/plugins/devtools/derive/answer-display/answer-display.js +1 -1
  7. package/dist/plugins/devtools/derive/answer-display/index.d.ts +2 -2
  8. package/dist/plugins/devtools/derive/answer-display/index.js +1 -1
  9. package/dist/plugins/devtools/derive/guide-sections/guide-sections.js +1 -1
  10. package/dist/plugins/devtools/derive/index.d.ts +5 -5
  11. package/dist/plugins/devtools/derive/index.js +1 -1
  12. package/dist/plugins/devtools/derive/personas/index.d.ts +2 -2
  13. package/dist/plugins/devtools/derive/personas/index.js +1 -1
  14. package/dist/plugins/devtools/derive/personas/personas.d.ts +88 -7
  15. package/dist/plugins/devtools/derive/personas/personas.js +1 -1
  16. package/dist/plugins/devtools/derive/plain-language/index.d.ts +1 -1
  17. package/dist/plugins/devtools/derive/plain-language/index.js +1 -1
  18. package/dist/plugins/devtools/derive/plain-language/plain-language.d.ts +5 -5
  19. package/dist/plugins/devtools/derive/plain-language/plain-language.js +1 -1
  20. package/dist/plugins/devtools/index.d.ts +1 -1
  21. package/dist/plugins/devtools/launcher/Launcher.svelte +13 -4
  22. package/dist/plugins/devtools/options.d.ts +6 -4
  23. package/dist/plugins/devtools/options.js +1 -1
  24. package/dist/plugins/devtools/review/journey/ExperienceDetails.svelte +129 -0
  25. package/dist/plugins/devtools/review/journey/JourneyPanel.svelte +54 -8
  26. package/dist/plugins/devtools/review/personas/ChoiceButton.svelte +40 -6
  27. package/dist/plugins/devtools/review/personas/PersonaBuilder.svelte +69 -45
  28. package/dist/plugins/devtools/review/personas/PersonaCard.svelte +226 -43
  29. package/dist/plugins/devtools/review/personas/PersonasPanel.svelte +171 -74
  30. package/dist/plugins/devtools/review/personas/load-persona.d.ts +41 -20
  31. package/dist/plugins/devtools/review/personas/load-persona.js +1 -1
  32. package/dist/plugins/devtools/review/personas/persona-route.d.ts +87 -0
  33. package/dist/plugins/devtools/review/personas/persona-route.js +1 -0
  34. package/dist/plugins/devtools/review/personas/persona-session.d.ts +94 -0
  35. package/dist/plugins/devtools/review/personas/persona-session.js +1 -0
  36. package/dist/plugins/devtools/sidebar/Sidebar.svelte +14 -48
  37. package/dist/plugins/devtools/sidebar/SidebarRow.svelte +2 -2
  38. package/dist/plugins/devtools/sidebar/nav.d.ts +26 -39
  39. package/dist/plugins/devtools/sidebar/nav.js +1 -1
  40. package/package.json +2 -2
  41. package/dist/plugins/devtools/screens/experience-instances/ExperienceInstancesListScreen.svelte +0 -10
  42. package/dist/plugins/devtools/screens/experiences/ExperienceDetailsScreen.svelte +0 -44
  43. package/dist/plugins/devtools/screens/experiences/ExperienceExperienceInstancesListScreen.svelte +0 -13
  44. package/dist/plugins/devtools/screens/experiences/ExperienceScreen.svelte +0 -32
  45. package/dist/plugins/devtools/screens/experiences/ExperienceTreeScreen.svelte +0 -500
  46. package/dist/plugins/devtools/screens/experiences/ExperiencesListScreen.svelte +0 -22
  47. package/dist/plugins/devtools/screens/features/FeaturesListScreen.svelte +0 -239
  48. package/dist/plugins/devtools/screens/responses/ResponseTableRow.svelte +0 -286
  49. package/dist/plugins/devtools/screens/responses/ResponsesListScreen.svelte +0 -12
  50. package/dist/plugins/devtools/screens/responses/ResponsesTable.svelte +0 -88
@@ -18,16 +18,14 @@
18
18
  import Sidebar from './sidebar/Sidebar.svelte'
19
19
  import SidebarFooter from './sidebar/SidebarFooter.svelte'
20
20
  import {
21
- CUSTOM_TOOLS_OPEN_STORAGE_KEY,
21
+ ADVANCED_OPEN_STORAGE_KEY,
22
22
  CUSTOM_TOOLS_TAB,
23
- DEVELOPER_OPEN_STORAGE_KEY,
24
23
  TAB_STORAGE_KEY,
25
24
  buildNav,
26
- developerTabId,
27
- isInCustomTools,
28
- isInDeveloper,
25
+ isInAdvanced,
29
26
  readStored,
30
27
  resolveTab,
28
+ screenTabId,
31
29
  toolTabId,
32
30
  writeStored,
33
31
  } from './sidebar/nav'
@@ -46,6 +44,7 @@
46
44
  TAB_INTROS,
47
45
  configSourceLabel,
48
46
  derivePosture,
47
+ applyEdits,
49
48
  guideFixes,
50
49
  guideSections,
51
50
  readSavedPersonas,
@@ -62,26 +61,31 @@
62
61
  VariationsPanel,
63
62
  } from './review'
64
63
  import {
64
+ openPersonaJourney,
65
65
  screenQuestions,
66
66
  takePendingLoad,
67
67
  walkNotice,
68
68
  walkPersona,
69
+ type PendingLoad,
69
70
  type WalkSettings,
70
71
  } from './review/personas/load-persona'
72
+ import {
73
+ prefillPersona,
74
+ readActivePersona,
75
+ takePersonaLink,
76
+ writeActivePersona,
77
+ type Prefill,
78
+ } from './review/personas/persona-session'
71
79
  import ProjectScreen from './screens/project/ProjectScreen.svelte'
72
80
  import ComponentsListScreen from './screens/components/ComponentsListScreen.svelte'
73
81
  import ConfigScreen from './screens/config/ConfigScreen.svelte'
74
82
  import ContentListScreen from './screens/content/ContentListScreen.svelte'
75
83
  import EventsListScreen from './screens/events/EventsListScreen.svelte'
76
- import ExperienceInstancesListScreen from './screens/experience-instances/ExperienceInstancesListScreen.svelte'
77
- import ExperiencesListScreen from './screens/experiences/ExperiencesListScreen.svelte'
78
- import FeaturesListScreen from './screens/features/FeaturesListScreen.svelte'
79
84
  import FieldsListScreen from './screens/fields/FieldsListScreen.svelte'
80
85
  import FrameworksListScreen from './screens/frameworks/FrameworksListScreen.svelte'
81
86
  import HistoryEntriesListScreen from './screens/history/HistoryEntriesListScreen.svelte'
82
87
  import IdentityScreen from './screens/identity/IdentityScreen.svelte'
83
88
  import PredicatesListScreen from './screens/predicates/PredicatesListScreen.svelte'
84
- import ResponsesListScreen from './screens/responses/ResponsesListScreen.svelte'
85
89
  import CustomToolsScreen from './screens/custom-tools/CustomToolsScreen.svelte'
86
90
 
87
91
  const experience = getExperience()
@@ -118,22 +122,18 @@
118
122
  const sessionStorageOf = (): Storage => window.sessionStorage
119
123
  const localStorageOf = (): Storage => window.localStorage
120
124
 
121
- /** The developer screens, keyed by their sidebar id. */
122
- const DEVELOPER_COMPONENTS: Record<string, Component> = {
123
- [developerTabId('project')]: ProjectScreen,
124
- [developerTabId('components')]: ComponentsListScreen,
125
- [developerTabId('config')]: ConfigScreen,
126
- [developerTabId('content')]: ContentListScreen,
127
- [developerTabId('events')]: EventsListScreen,
128
- [developerTabId('experience-instances')]: ExperienceInstancesListScreen,
129
- [developerTabId('experiences')]: ExperiencesListScreen,
130
- [developerTabId('features')]: FeaturesListScreen,
131
- [developerTabId('fields')]: FieldsListScreen,
132
- [developerTabId('frameworks')]: FrameworksListScreen,
133
- [developerTabId('history')]: HistoryEntriesListScreen,
134
- [developerTabId('identity')]: IdentityScreen,
135
- [developerTabId('predicates')]: PredicatesListScreen,
136
- [developerTabId('responses')]: ResponsesListScreen,
125
+ /** The SDK's own screens, keyed by their sidebar id. */
126
+ const SCREEN_COMPONENTS: Record<string, Component> = {
127
+ [screenTabId('project')]: ProjectScreen,
128
+ [screenTabId('components')]: ComponentsListScreen,
129
+ [screenTabId('config')]: ConfigScreen,
130
+ [screenTabId('content')]: ContentListScreen,
131
+ [screenTabId('events')]: EventsListScreen,
132
+ [screenTabId('fields')]: FieldsListScreen,
133
+ [screenTabId('frameworks')]: FrameworksListScreen,
134
+ [screenTabId('history')]: HistoryEntriesListScreen,
135
+ [screenTabId('identity')]: IdentityScreen,
136
+ [screenTabId('predicates')]: PredicatesListScreen,
137
137
  }
138
138
 
139
139
  // ── The session record ───────────────────────────────────────────────────────────────────────
@@ -169,26 +169,24 @@
169
169
  )
170
170
  const storedTab = readStored(sessionStorageOf, TAB_STORAGE_KEY)
171
171
  let tab = $state(storedTab ?? 'guide')
172
- let developerOpen = $state(readStored(sessionStorageOf, DEVELOPER_OPEN_STORAGE_KEY) === 'true')
173
- let customOpen = $state(readStored(sessionStorageOf, CUSTOM_TOOLS_OPEN_STORAGE_KEY) !== 'false')
172
+ let advancedOpen = $state(readStored(sessionStorageOf, ADVANCED_OPEN_STORAGE_KEY) === 'true')
174
173
  let drawerOpen = $state(false)
175
174
 
176
175
  // A tab can disappear under the viewer (Feature flags once the feature list is empty), and a
177
- // stored developer screen opens its group.
176
+ // stored Advanced screen opens its group.
178
177
  $effect(() => {
179
178
  const resolved = resolveTab(tab, nav)
180
179
  if (resolved !== tab) tab = resolved
181
- if (isInDeveloper(tab, nav) && !developerOpen) developerOpen = true
182
- if (isInCustomTools(tab, nav) && !customOpen) customOpen = true
180
+ if (isInAdvanced(tab, nav) && !advancedOpen) advancedOpen = true
183
181
  })
184
182
 
185
183
  const selectedItem = $derived(
186
- [...nav.primary, ...nav.custom, ...nav.developer, ...nav.footer].find((item) => item.id === tab),
184
+ [...nav.primary, ...nav.advanced, ...nav.footer].find((item) => item.id === tab),
187
185
  )
188
186
  const selectedTool = $derived(
189
187
  [...tools, ...customTools, ...footer].find((tool) => toolTabId(tool.id) === tab),
190
188
  )
191
- const developerScreen = $derived(DEVELOPER_COMPONENTS[tab])
189
+ const sdkScreen = $derived(SCREEN_COMPONENTS[tab])
192
190
 
193
191
  /**
194
192
  * Narrows a tab id to one of the review tabs.
@@ -214,23 +212,13 @@
214
212
  }
215
213
 
216
214
  /**
217
- * Opens or folds the Custom Tools group, and remembers it.
215
+ * Opens or folds the Advanced group, and remembers it.
218
216
  *
219
- * @example toggleCustom()
217
+ * @example toggleAdvanced()
220
218
  */
221
- function toggleCustom(): void {
222
- customOpen = !customOpen
223
- writeStored(sessionStorageOf, CUSTOM_TOOLS_OPEN_STORAGE_KEY, String(customOpen))
224
- }
225
-
226
- /**
227
- * Opens or folds the Developer group, and remembers it.
228
- *
229
- * @example toggleDeveloper()
230
- */
231
- function toggleDeveloper(): void {
232
- developerOpen = !developerOpen
233
- writeStored(sessionStorageOf, DEVELOPER_OPEN_STORAGE_KEY, String(developerOpen))
219
+ function toggleAdvanced(): void {
220
+ advancedOpen = !advancedOpen
221
+ writeStored(sessionStorageOf, ADVANCED_OPEN_STORAGE_KEY, String(advancedOpen))
234
222
  }
235
223
 
236
224
  // ── How to use ───────────────────────────────────────────────────────────────────────────────
@@ -262,7 +250,7 @@
262
250
  sections: guideSections(available, { lead, tools: toolSections }),
263
251
  fixes: guideFixes(available, options.guide.fixes),
264
252
  tabLabels: Object.fromEntries(
265
- [...nav.primary, ...nav.custom, ...nav.footer].map((item) => [item.id, item.label]),
253
+ [...nav.primary, ...nav.footer].map((item) => [item.id, item.label]),
266
254
  ),
267
255
  }
268
256
  })
@@ -285,14 +273,22 @@
285
273
  writeAutoHide(localStorageOf, value)
286
274
  }
287
275
 
288
- // ── A persona load, carried across its reload ────────────────────────────────────────────────
289
- // Load reloads the page clean, so the walk runs here, as the devtools mount on the new page. The
290
- // panel stays shut while it walks, so the reviewer watches the journey move, and opens on the
291
- // Personas tab when the walk stops short.
276
+ // ── A persona session, carried across reloads ──────────────────────────────────────────────
277
+ // Walk through and Jump to step reload the page clean, so the session starts here, as the
278
+ // devtools mount on the new page, and again on every later page of the tab until Stop. Each
279
+ // start runs the persona's setup and pre-fills every step with its responses. A jump walks to
280
+ // its step first, with the panel shut so the reviewer watches the journey move, and opens on the
281
+ // Personas tab when the walk stops short. A shared link starts a walk-through on the page it
282
+ // opens.
292
283
  let personaWalkNotice = $state<{
293
284
  status: 'info' | 'success' | 'warning' | 'error'
294
285
  text: string
295
286
  } | null>(null)
287
+ /** The site's personas, once the option has loaded them. */
288
+ let sitePersonaList = $state.raw<Persona[]>([])
289
+ /** The persona this tab walks through as. */
290
+ let activePersona = $state.raw<Persona | null>(null)
291
+ let prefill: Prefill | null = null
296
292
 
297
293
  const walkSettings: WalkSettings = {
298
294
  exclude: options.hiddenExperienceKeys,
@@ -304,30 +300,108 @@
304
300
  }
305
301
 
306
302
  /**
307
- * The persona a reload was for, among the site's and this browser's.
303
+ * A persona by id, among the site's as this browser edited them and this browser's own.
304
+ *
305
+ * @param {string} id - The persona's id.
306
+ * @param {readonly Persona[]} site - The site's personas.
307
+ * @returns {Persona | undefined} The persona, or `undefined` when none has the id.
308
+ * @example findPersona('mover', sitePersonaList)
309
+ */
310
+ function findPersona(id: string, site: readonly Persona[]): Persona | undefined {
311
+ const listed = applyEdits(site, readSavedPersonas(localStorageOf, client.projectId))
312
+ return [...listed.site, ...listed.own].find((persona) => persona.id === id)
313
+ }
314
+
315
+ /**
316
+ * Walks a jump to its step, then says how it went, opening the panel when it stopped short.
317
+ *
318
+ * @param {Persona} persona - The persona.
319
+ * @param {PendingLoad} pending - The jump.
320
+ * @returns {Promise<void>} Settles once the walk ends.
321
+ * @example await jump(persona, pending)
322
+ */
323
+ async function jump(persona: Persona, pending: PendingLoad): Promise<void> {
324
+ const stepName = pending.stop?.stepName ?? pending.stop?.stepKey ?? ''
325
+ personaWalkNotice = { status: 'info', text: `Jumping to “${stepName}” as ${persona.name}…` }
326
+ const outcome = await walkPersona(
327
+ client,
328
+ { ...persona, landing: pending.stop, passed: pending.passed },
329
+ walkSettings,
330
+ )
331
+ const notice = walkNotice(persona, outcome)
332
+ personaWalkNotice = notice
333
+ if (notice.status === 'success') return
334
+ selectTab('personas')
335
+ experience.open()
336
+ }
337
+
338
+ /**
339
+ * Starts or resumes this tab's persona session: a reload's start, a shared link, or the session
340
+ * a reload carried on.
308
341
  *
309
- * @returns {Persona | undefined} The persona, or `undefined` when no load is waiting.
310
- * @example pendingPersona()
342
+ * @returns {Promise<void>} Settles once the persona is set up and any jump has walked.
343
+ * @example await startPersonaSession()
311
344
  */
312
- function pendingPersona(): Persona | undefined {
313
- const id = takePendingLoad(sessionStorageOf())
314
- if (id === null || !posture.canEditAnswers) return undefined
315
- const saved = readSavedPersonas(localStorageOf, client.projectId)
316
- return [...options.personas, ...saved].find((persona) => persona.id === id)
317
- }
318
-
319
- const walking = pendingPersona()
320
- if (walking !== undefined) {
321
- personaWalkNotice = { status: 'info', text: `Loading ${walking.name}…` }
322
- void walkPersona(client, walking, walkSettings).then((outcome) => {
323
- const notice = walkNotice(walking, outcome)
324
- personaWalkNotice = notice
325
- if (notice.status === 'success') return
326
- selectTab('personas')
327
- experience.open()
345
+ async function startPersonaSession(): Promise<void> {
346
+ const storage = sessionStorageOf()
347
+ const pending = takePendingLoad(storage)
348
+ const linked = takePersonaLink(window.location, (url) => {
349
+ window.history.replaceState(window.history.state, '', url)
328
350
  })
351
+ const site = await options.personas()
352
+ sitePersonaList = site
353
+ const id = pending?.id ?? linked ?? readActivePersona(storage)
354
+ if (id === null || !posture.canEditAnswers) return
355
+ const persona = findPersona(id, site)
356
+ if (persona === undefined || (pending === null && linked !== null && persona.source !== 'site')) {
357
+ writeActivePersona(storage, null)
358
+ return
359
+ }
360
+
361
+ writeActivePersona(storage, persona.id)
362
+ activePersona = persona
363
+ try {
364
+ await persona.setup?.(client)
365
+ } catch (error) {
366
+ const detail = error instanceof Error ? ` ${error.message}` : ''
367
+ personaWalkNotice = { status: 'error', text: `${persona.name}’s setup failed.${detail}` }
368
+ }
369
+
370
+ prefill = prefillPersona(
371
+ client,
372
+ { ...persona.responses, ...options.personaWalk.responses },
373
+ session.askedStore,
374
+ )
375
+ if (pending?.stop != null) await jump(persona, pending)
376
+ else if (pending !== null || linked !== null) {
377
+ await openPersonaJourney(client, persona, walkSettings)
378
+ }
329
379
  }
330
380
 
381
+ /**
382
+ * Ends this tab's persona session: every field gets its own default back.
383
+ *
384
+ * @example stopPersonaSession()
385
+ */
386
+ function stopPersonaSession(): void {
387
+ prefill?.stop()
388
+ prefill = null
389
+ writeActivePersona(sessionStorageOf(), null)
390
+ if (activePersona !== null) {
391
+ personaWalkNotice = {
392
+ status: 'success',
393
+ text: `Stopped walking through as ${activePersona.name}. Fields already filled in keep their values.`,
394
+ }
395
+ }
396
+
397
+ activePersona = null
398
+ }
399
+
400
+ void startPersonaSession()
401
+ $effect(() => () => {
402
+ prefill?.stop()
403
+ })
404
+
331
405
  // ── Dialog behaviour ─────────────────────────────────────────────────────────────────────────
332
406
  /** The open panel; Svelte sets it back to `null` when the panel unmounts. */
333
407
  let panel: HTMLDivElement | null = $state(null)
@@ -456,11 +530,9 @@
456
530
  <Sidebar
457
531
  {nav}
458
532
  selected={tab}
459
- {developerOpen}
460
- {customOpen}
533
+ {advancedOpen}
461
534
  onSelect={selectTab}
462
- onToggleDeveloper={toggleDeveloper}
463
- onToggleCustom={toggleCustom}
535
+ onToggleAdvanced={toggleAdvanced}
464
536
  />
465
537
  <SidebarFooter
466
538
  tools={nav.footer}
@@ -472,9 +544,9 @@
472
544
  </div>
473
545
 
474
546
  <section class="pane" aria-label={selectedItem?.label} data-testid="devtools-pane">
475
- {#if developerScreen}
476
- {@const Screen = developerScreen}
477
- <div class="developer-body">
547
+ {#if sdkScreen}
548
+ {@const Screen = sdkScreen}
549
+ <div class="screen-body">
478
550
  <Screen />
479
551
  </div>
480
552
  {:else if tab === CUSTOM_TOOLS_TAB}
@@ -533,13 +605,15 @@
533
605
  {client}
534
606
  {posture}
535
607
  journey={$journey}
536
- personas={options.personas}
608
+ personas={sitePersonaList}
537
609
  asked={$asked}
538
610
  route={$route}
539
611
  hiddenKeys={options.hiddenExperienceKeys}
540
612
  codeOwned={options.codeOwnedFields}
541
613
  personaWalk={options.personaWalk}
542
614
  tools={personaTools}
615
+ {activePersona}
616
+ onStop={stopPersonaSession}
543
617
  walkNotice={personaWalkNotice}
544
618
  onWalkNoticeDismiss={() => (personaWalkNotice = null)}
545
619
  />
@@ -557,6 +631,7 @@
557
631
  position={options.launcher.position}
558
632
  {autoHide}
559
633
  {preview}
634
+ walkingAs={activePersona?.name ?? null}
560
635
  onOpen={() => experience.open()}
561
636
  />
562
637
  {/if}
@@ -824,7 +899,7 @@
824
899
  display: grid;
825
900
  }
826
901
 
827
- .developer-body {
902
+ .screen-body {
828
903
  flex: 1 1 auto;
829
904
  display: grid;
830
905
  min-height: 0;
@@ -28,7 +28,7 @@ export interface CustomTool {
28
28
  * `'review'` lists the tool as a tab of its own, beside the review tabs. `'personas'` shows it
29
29
  * as a section of the Personas & Scenarios tab, under its label. `'footer'` shows it as an icon
30
30
  * at the foot of the sidebar, beside the auto-hide switch, with its label as a tooltip.
31
- * `'developer'` lists it as a row of its own in the sidebar's Custom Tools group.
31
+ * `'developer'` lists it as a top-level row of its own, after the review-placed tools.
32
32
  *
33
33
  * @default 'developer'
34
34
  */
@@ -82,7 +82,7 @@ export declare function personasTools(tools: readonly CustomTool[]): CustomTool[
82
82
  */
83
83
  export declare function footerTools(tools: readonly CustomTool[]): CustomTool[];
84
84
  /**
85
- * The tools listed in the sidebar's Custom Tools group.
85
+ * The tools listed as top-level rows after the review-placed tools.
86
86
  *
87
87
  * @param {readonly CustomTool[]} tools - The registered tools.
88
88
  * @returns {CustomTool[]} The unplaced tools and those placed `'developer'`, in registration order.
@@ -53,6 +53,20 @@ export declare function questionOf(field: AnswerField): string;
53
53
  * kindOf({ key: 'quote', type: 'object', multiple: false }) // 'system'
54
54
  */
55
55
  export declare function kindOf(field: AnswerField): AnswerKind;
56
+ /** How a question is drawn for a reviewer to answer, as a site draws it from the same config. */
57
+ export type InputStyle = 'tiles' | 'pills' | 'checkboxes' | 'yes-no' | 'number' | 'text' | 'system';
58
+ /**
59
+ * How a question is drawn, from its field's config alone: a single choice of up to eight options
60
+ * as tiles and of more as pills, a multiple choice as checkboxes, a yes-or-no question as two
61
+ * tiles, and anything else as its own input.
62
+ *
63
+ * @param {AnswerField} field - The field.
64
+ * @param {number} offered - How many of its options the step offers.
65
+ * @returns {InputStyle} The style to draw it in.
66
+ * @example
67
+ * inputStyleOf(coverLevel, 3) // 'tiles'
68
+ */
69
+ export declare function inputStyleOf(field: AnswerField, offered: number): InputStyle;
56
70
  /**
57
71
  * Renders an answer for display. An object value is summarised rather than dumped; the panel
58
72
  * offers Copy for the reviewer who wants the payload.
@@ -1 +1 @@
1
- import{deslug as e}from"../plain-language/plain-language.js";var t=`No response yet`,n=`Set on its step`;function r(t){let n=t.name?.trim();return n!==void 0&&n.length>0?n:e(t.key)}function i(e){let t=e.label?.trim();return t!==void 0&&t.length>0?t:r(e)}function a(e){return e.type===`object`?`system`:e.options!==null&&e.options!==void 0&&e.options.length>0?`options`:e.type===`boolean`?`boolean`:e.type===`number`?`number`:`text`}function o(e,n){let r=n.options?.find(t=>t.value===e);return r===void 0?e===!0?`Yes`:e===!1?`No`:e===null?t:typeof e==`string`?e:typeof e==`number`?String(e):JSON.stringify(e):r.label}function s(e,t){return e==null||e===``?null:Array.isArray(e)?e.length===0?null:e.map(e=>o(e,t)).join(`, `):a(t)===`system`?n:o(e,t)}function c(e,t){let n=a(t),o=s(e,t);return{title:i(t),noun:r(t),kind:n,display:o,answered:o!==null,editable:n!==`system`}}function l(e,t,n=new Set){let r=new Set;for(let e of t)for(let t of e)t.type===`step`&&t.stepId!==void 0&&r.add(t.stepId);let i=new Set;for(let t of e)if(r.has(t.id))for(let e of t.fieldKeys)n.has(e)||i.add(e);return i}function u(e){return e===void 0?``:JSON.stringify(e,null,2)}export{l as askedFieldKeys,c as describeAnswer,a as kindOf,r as nounOf,i as questionOf,s as renderAnswer,u as systemPayload};
1
+ import{deslug as e}from"../plain-language/plain-language.js";var t=`No response yet`,n=`Set on its step`;function r(t){let n=t.name?.trim();return n!==void 0&&n.length>0?n:e(t.key)}function i(e){let t=e.label?.trim();return t!==void 0&&t.length>0?t:r(e)}function a(e){return e.type===`object`?`system`:e.options!==null&&e.options!==void 0&&e.options.length>0?`options`:e.type===`boolean`?`boolean`:e.type===`number`?`number`:`text`}var o=8;function s(e,t){let n=a(e);return n===`options`?e.multiple?`checkboxes`:t<=o?`tiles`:`pills`:n===`boolean`?`yes-no`:n}function c(e,n){let r=n.options?.find(t=>t.value===e);return r===void 0?e===!0?`Yes`:e===!1?`No`:e===null?t:typeof e==`string`?e:typeof e==`number`?String(e):JSON.stringify(e):r.label}function l(e,t){return e==null||e===``?null:Array.isArray(e)?e.length===0?null:e.map(e=>c(e,t)).join(`, `):a(t)===`system`?n:c(e,t)}function u(e,t){let n=a(t),o=l(e,t);return{title:i(t),noun:r(t),kind:n,display:o,answered:o!==null,editable:n!==`system`}}function d(e,t,n=new Set){let r=new Set;for(let e of t)for(let t of e)t.type===`step`&&t.stepId!==void 0&&r.add(t.stepId);let i=new Set;for(let t of e)if(r.has(t.id))for(let e of t.fieldKeys)n.has(e)||i.add(e);return i}function f(e){return e===void 0?``:JSON.stringify(e,null,2)}export{d as askedFieldKeys,u as describeAnswer,s as inputStyleOf,a as kindOf,r as nounOf,i as questionOf,l as renderAnswer,f as systemPayload};
@@ -1,3 +1,3 @@
1
1
  /** @file Public entrypoint for how an answer is shown to a reviewer and whether it is editable. */
2
- export { askedFieldKeys, describeAnswer, kindOf, nounOf, questionOf, renderAnswer, systemPayload, } from './answer-display';
3
- export type { AnswerField, AnswerKind, AnswerView, AskedNode, AskedStep } from './answer-display';
2
+ export { askedFieldKeys, describeAnswer, inputStyleOf, kindOf, nounOf, questionOf, renderAnswer, systemPayload, } from './answer-display';
3
+ export type { AnswerField, AnswerKind, AnswerView, AskedNode, AskedStep, InputStyle, } from './answer-display';
@@ -1 +1 @@
1
- export{askedFieldKeys,describeAnswer,kindOf,nounOf,questionOf,renderAnswer,systemPayload}from"./answer-display.js";
1
+ export{askedFieldKeys,describeAnswer,inputStyleOf,kindOf,nounOf,questionOf,renderAnswer,systemPayload}from"./answer-display.js";
@@ -1 +1 @@
1
- var e=[{id:`session`,title:`See where you are`,steps:[],notes:[`To see the step you are on and every response so far, open **This session**.`],tab:`session`},{id:`answers`,title:`Change a response`,steps:[`Open **Responses**.`,`Find the field. Use **With a response**, **No response** or **All** to narrow the list.`,`Click **Change**, or **Add** if it has no response yet.`,`Pick or type the new response, then click **Save**.`],notes:[`To remove one response, click **Clear** beside it.`,`To start the whole experience again, click **Start over**, then **Clear everything**.`,`If a field says **Change it on its step**, go back to that step and change it there.`],tab:`answers`},{id:`journey`,title:`Go back to an earlier step`,steps:[`Open **Flow**.`,`Find a step on your route. Your route is blue, and your step says **You are here**.`,`Click the step, then click **Go back to this step**.`],notes:[`You can only go back to steps you have already visited.`,`To change how the flow is drawn, pick **Map**, **Timeline** or **Outline** at the top.`],tab:`journey`},{id:`personas`,title:`Try the experience as a visitor`,steps:[`Open **Personas & Scenarios**.`,`Click **Load** beside the visitor you want. The experience opens where they would be.`],notes:[`To keep where you are for later, click **Create**, give it a name, then click **Save**.`,`What you save stays in this browser only.`],tab:`personas`},{id:`variations`,title:`View a feature flag variant`,steps:[`Open **Feature flags**.`,`Find the feature flag and pick the variant you want.`,`Click **Show me this variant**. The page reloads showing it.`,`To share exactly what you saw, click **Copy link** and send it.`],notes:[`To go back to normal for that feature flag, click **Leave this one alone**.`],tab:`variations`}],t=[{tab:`journey`,entry:{problem:`I can't click a step in the Flow tab`,fix:`Go back only to steps you have visited.`}}];function n(e,t){return e!==`variations`||t.variations}function r(t,r){return[...r?.lead??[],...e.filter(e=>n(e.tab,t)),...r?.tools??[]]}function i(e,r){return[...t.filter(t=>n(t.tab,e)).map(e=>e.entry),...r??[]]}function a(e){let t=e.split(`**`);return t.length%2==0?[{text:e,bold:!1}]:t.map((e,t)=>({text:e,bold:t%2==1})).filter(e=>e.text.length>0)}export{a as emphasis,i as guideFixes,r as guideSections};
1
+ var e=[{id:`session`,title:`See where you are`,steps:[],notes:[`To see the step you are on and every response so far, open **This session**.`],tab:`session`},{id:`answers`,title:`Change a response`,steps:[`Open **Responses**.`,`Find the field. Use **With a response**, **No response** or **All** to narrow the list.`,`Click **Change**, or **Add** if it has no response yet.`,`Pick or type the new response, then click **Save**.`],notes:[`To remove one response, click **Clear** beside it.`,`To start the whole experience again, click **Start over**, then **Clear everything**.`,`If a field says **Change it on its step**, go back to that step and change it there.`],tab:`answers`},{id:`journey`,title:`Go back to an earlier step`,steps:[`Open **Experiences**.`,`Find a step on your route. Your route is blue, and your step says **You are here**.`,`Click the step, then click **Go back to this step**.`],notes:[`You can only go back to steps you have already visited.`,`To change how the flow is drawn, pick **Map**, **Timeline** or **Outline** at the top.`,`To see where an experience shows and when it starts, pick **Details**.`,`To open an experience that is not on the page, pick it, then click **Launch experience**.`],tab:`journey`},{id:`personas`,title:`Try the experience as a visitor`,steps:[`Open **Personas & Scenarios**.`,`Click **Walk through** beside the visitor you want. The page starts again.`,`Go through the experience. Each step shows their responses. Click **Continue**, or change a response first.`,`When you are done, click **Stop** at the top of the tab.`],notes:[`To start further in, click **Jump to step**, then pick the step.`,`To change a persona, click **Edit**. Your change stays in this browser only.`,`To keep where you are for later, click **Create**, give it a name, then click **Save**.`,`To send a site persona to someone else, click its copy icon and share the link.`],tab:`personas`},{id:`variations`,title:`View a feature flag variant`,steps:[`Open **Feature flags**.`,`Find the feature flag and pick the variant you want.`,`Click **Show me this variant**. The page reloads showing it.`,`To share exactly what you saw, click **Copy link** and send it.`],notes:[`To go back to normal for that feature flag, click **Leave this one alone**.`],tab:`variations`}],t=[{tab:`journey`,entry:{problem:`I can't click a step in the Experiences tab`,fix:`Go back only to steps you have visited.`}}];function n(e,t){return e!==`variations`||t.variations}function r(t,r){return[...r?.lead??[],...e.filter(e=>n(e.tab,t)),...r?.tools??[]]}function i(e,r){return[...t.filter(t=>n(t.tab,e)).map(e=>e.entry),...r??[]]}function a(e){let t=e.split(`**`);return t.length%2==0?[{text:e,bold:!1}]:t.map((e,t)=>({text:e,bold:t%2==1})).filter(e=>e.text.length>0)}export{a as emphasis,i as guideFixes,r as guideSections};
@@ -2,8 +2,8 @@
2
2
  * @file Public entrypoint for the review tools' pure derivations. Every panel stays thin by pushing
3
3
  * its thinking here, where it is tested off plain objects with no client, no DOM and no store.
4
4
  */
5
- export { askedFieldKeys, describeAnswer, kindOf, nounOf, questionOf, renderAnswer, systemPayload, } from './answer-display';
6
- export type { AnswerField, AnswerKind, AnswerView, AskedNode, AskedStep } from './answer-display';
5
+ export { askedFieldKeys, describeAnswer, inputStyleOf, kindOf, nounOf, questionOf, renderAnswer, systemPayload, } from './answer-display';
6
+ export type { AnswerField, AnswerKind, AnswerView, AskedNode, AskedStep, InputStyle, } from './answer-display';
7
7
  export { isBlank, nextHistory, submittedAnswers } from './answer-history';
8
8
  export type { HistoryAnswer, HistoryEntry, HistoryEvent } from './answer-history';
9
9
  export { emphasis, guideFixes, guideSections } from './guide-sections';
@@ -16,12 +16,12 @@ export { COLOURS, LANE_WIDTH, ROW_HEIGHT, buildTimeline } from './journey-timeli
16
16
  export type { TimelineEdge, TimelineLayout, TimelineNext, TimelineNode } from './journey-timeline';
17
17
  export { BREADTH, DEPTH, buildTree } from './journey-tree';
18
18
  export type { FlowEnd, TreeInput, TreeJump, TreeLayout, TreeLink, TreeNode, TreeNodeKind, } from './journey-tree';
19
- export { DEVELOPER_LABEL, NODE_LABELS, TAB_INTROS, TAB_LABELS, configSourceLabel, deslug, screenName, } from './plain-language';
19
+ export { NODE_LABELS, TAB_INTROS, ADVANCED_LABEL, TAB_LABELS, configSourceLabel, deslug, screenName, } from './plain-language';
20
20
  export type { ReviewTabId } from './plain-language';
21
21
  export { builderGraph, responseKeysOf, walkDraft } from './persona-builder';
22
22
  export type { BuilderCondition, BuilderEdge, BuilderField, BuilderInput, BuilderJourney, BuilderNode, BuilderRow, BuilderStep, BuilderWalk, GraphSource, } from './persona-builder';
23
- export { PERSONA_STORAGE_PREFIX, buildPersona, customerAnswers, describeLanding, entryUrlOf, passedScreens, personaStorageKey, readAnswers, readEntryUrl, readSavedPersonas, sitePersonas, writeSavedPersonas, } from './personas';
24
- export type { BuildPersonaResult, Persona, PersonaCapture, PersonaDefinition, PersonaDraft, PersonaLanding, PersonaLoader, PersonaScreen, PersonaSource, PersonaStorageGetter, } from './personas';
23
+ export { PERSONA_STORAGE_PREFIX, applyEdits, buildPersona, customerAnswers, describeLanding, entryUrlOf, groupPersonas, matchesSearch, passedScreens, personaStorageKey, readAnswers, readEntryUrl, readLanding, readPassed, readSavedPersonas, sitePersonas, startOf, writeSavedPersonas, } from './personas';
24
+ export type { BuildPersonaResult, EditedPersonas, Persona, PersonaCapture, PersonaDefinition, PersonaDraft, PersonaGroup, PersonaLanding, PersonaScreen, PersonaSetup, PersonaSource, PersonaStorageGetter, } from './personas';
25
25
  export { UNDESCRIBABLE, describeRule, varKeyOf } from './plain-logic';
26
26
  export type { FieldLookup, FieldSummary } from './plain-logic';
27
27
  export { derivePosture } from './safety-posture';
@@ -1 +1 @@
1
- import{isBlank as e,nextHistory as t,submittedAnswers as n}from"./answer-history/answer-history.js";import{DEVELOPER_LABEL as r,NODE_LABELS as i,TAB_INTROS as a,TAB_LABELS as o,configSourceLabel as s,deslug as c,screenName as l}from"./plain-language/plain-language.js";import{PERSONA_STORAGE_PREFIX as u,buildPersona as d,customerAnswers as f,describeLanding as p,entryUrlOf as m,passedScreens as h,personaStorageKey as g,readAnswers as _,readEntryUrl as v,readSavedPersonas as y,sitePersonas as b,writeSavedPersonas as x}from"./personas/personas.js";import{askedFieldKeys as S,describeAnswer as C,kindOf as w,nounOf as T,questionOf as E,renderAnswer as D,systemPayload as O}from"./answer-display/answer-display.js";import{emphasis as k,guideFixes as A,guideSections as j}from"./guide-sections/guide-sections.js";import{UNDESCRIBABLE as M,describeRule as N,varKeyOf as P}from"./plain-logic/plain-logic.js";import{buildOutline as F}from"./journey-outline/journey-outline.js";import{nextOpenOrder as I,pickJourney as L}from"./journey-pick/journey-pick.js";import{BREADTH as R,DEPTH as z,buildTree as B}from"./journey-tree/journey-tree.js";import"./journey-tree/index.js";import{COLOURS as V,LANE_WIDTH as H,ROW_HEIGHT as U,buildTimeline as W}from"./journey-timeline/journey-timeline.js";import"./journey-timeline/index.js";import{builderGraph as G,responseKeysOf as K,walkDraft as q}from"./persona-builder/persona-builder.js";import{derivePosture as J}from"./safety-posture/safety-posture.js";import{nextTrails as Y}from"./visited-steps/visited-steps.js";import{nextRoute as X}from"./walk-route/walk-route.js";export{R as BREADTH,V as COLOURS,z as DEPTH,r as DEVELOPER_LABEL,H as LANE_WIDTH,i as NODE_LABELS,u as PERSONA_STORAGE_PREFIX,U as ROW_HEIGHT,a as TAB_INTROS,o as TAB_LABELS,M as UNDESCRIBABLE,S as askedFieldKeys,F as buildOutline,d as buildPersona,W as buildTimeline,B as buildTree,G as builderGraph,s as configSourceLabel,f as customerAnswers,J as derivePosture,C as describeAnswer,p as describeLanding,N as describeRule,c as deslug,k as emphasis,m as entryUrlOf,A as guideFixes,j as guideSections,e as isBlank,w as kindOf,t as nextHistory,I as nextOpenOrder,X as nextRoute,Y as nextTrails,T as nounOf,h as passedScreens,g as personaStorageKey,L as pickJourney,E as questionOf,_ as readAnswers,v as readEntryUrl,y as readSavedPersonas,D as renderAnswer,K as responseKeysOf,l as screenName,b as sitePersonas,n as submittedAnswers,O as systemPayload,P as varKeyOf,q as walkDraft,x as writeSavedPersonas};
1
+ import{isBlank as e,nextHistory as t,submittedAnswers as n}from"./answer-history/answer-history.js";import{ADVANCED_LABEL as r,NODE_LABELS as i,TAB_INTROS as a,TAB_LABELS as o,configSourceLabel as s,deslug as c,screenName as l}from"./plain-language/plain-language.js";import{PERSONA_STORAGE_PREFIX as u,applyEdits as d,buildPersona as f,customerAnswers as p,describeLanding as m,entryUrlOf as h,groupPersonas as g,matchesSearch as _,passedScreens as v,personaStorageKey as y,readAnswers as b,readEntryUrl as x,readLanding as S,readPassed as C,readSavedPersonas as w,sitePersonas as T,startOf as E,writeSavedPersonas as D}from"./personas/personas.js";import{askedFieldKeys as O,describeAnswer as k,inputStyleOf as A,kindOf as j,nounOf as M,questionOf as N,renderAnswer as P,systemPayload as F}from"./answer-display/answer-display.js";import{emphasis as I,guideFixes as L,guideSections as R}from"./guide-sections/guide-sections.js";import{UNDESCRIBABLE as z,describeRule as B,varKeyOf as V}from"./plain-logic/plain-logic.js";import{buildOutline as H}from"./journey-outline/journey-outline.js";import{nextOpenOrder as U,pickJourney as W}from"./journey-pick/journey-pick.js";import{BREADTH as G,DEPTH as K,buildTree as q}from"./journey-tree/journey-tree.js";import"./journey-tree/index.js";import{COLOURS as J,LANE_WIDTH as Y,ROW_HEIGHT as X,buildTimeline as Z}from"./journey-timeline/journey-timeline.js";import"./journey-timeline/index.js";import{builderGraph as Q,responseKeysOf as $,walkDraft as ee}from"./persona-builder/persona-builder.js";import{derivePosture as te}from"./safety-posture/safety-posture.js";import{nextTrails as ne}from"./visited-steps/visited-steps.js";import{nextRoute as re}from"./walk-route/walk-route.js";export{r as ADVANCED_LABEL,G as BREADTH,J as COLOURS,K as DEPTH,Y as LANE_WIDTH,i as NODE_LABELS,u as PERSONA_STORAGE_PREFIX,X as ROW_HEIGHT,a as TAB_INTROS,o as TAB_LABELS,z as UNDESCRIBABLE,d as applyEdits,O as askedFieldKeys,H as buildOutline,f as buildPersona,Z as buildTimeline,q as buildTree,Q as builderGraph,s as configSourceLabel,p as customerAnswers,te as derivePosture,k as describeAnswer,m as describeLanding,B as describeRule,c as deslug,I as emphasis,h as entryUrlOf,g as groupPersonas,L as guideFixes,R as guideSections,A as inputStyleOf,e as isBlank,j as kindOf,_ as matchesSearch,t as nextHistory,U as nextOpenOrder,re as nextRoute,ne as nextTrails,M as nounOf,v as passedScreens,y as personaStorageKey,W as pickJourney,N as questionOf,b as readAnswers,x as readEntryUrl,S as readLanding,C as readPassed,w as readSavedPersonas,P as renderAnswer,$ as responseKeysOf,l as screenName,T as sitePersonas,E as startOf,n as submittedAnswers,F as systemPayload,V as varKeyOf,ee as walkDraft,D as writeSavedPersonas};
@@ -1,3 +1,3 @@
1
1
  /** @file Public entrypoint for personas: building, saving, reading and describing them. */
2
- export { PERSONA_STORAGE_PREFIX, buildPersona, customerAnswers, describeLanding, entryUrlOf, passedScreens, personaStorageKey, readAnswers, readEntryUrl, readSavedPersonas, sitePersonas, writeSavedPersonas, } from './personas';
3
- export type { BuildPersonaResult, Persona, PersonaCapture, PersonaDefinition, PersonaDraft, PersonaLanding, PersonaLoader, PersonaScreen, PersonaSource, PersonaStorageGetter, } from './personas';
2
+ export { PERSONA_STORAGE_PREFIX, applyEdits, buildPersona, customerAnswers, describeLanding, entryUrlOf, groupPersonas, matchesSearch, passedScreens, personaStorageKey, readAnswers, readEntryUrl, readLanding, readPassed, readSavedPersonas, sitePersonas, startOf, writeSavedPersonas, } from './personas';
3
+ export type { BuildPersonaResult, EditedPersonas, Persona, PersonaCapture, PersonaDefinition, PersonaDraft, PersonaGroup, PersonaLanding, PersonaScreen, PersonaSetup, PersonaSource, PersonaStorageGetter, } from './personas';
@@ -1 +1 @@
1
- export{PERSONA_STORAGE_PREFIX,buildPersona,customerAnswers,describeLanding,entryUrlOf,passedScreens,personaStorageKey,readAnswers,readEntryUrl,readSavedPersonas,sitePersonas,writeSavedPersonas}from"./personas.js";
1
+ export{PERSONA_STORAGE_PREFIX,applyEdits,buildPersona,customerAnswers,describeLanding,entryUrlOf,groupPersonas,matchesSearch,passedScreens,personaStorageKey,readAnswers,readEntryUrl,readLanding,readPassed,readSavedPersonas,sitePersonas,startOf,writeSavedPersonas}from"./personas.js";