@erclx/canon 5.52.0 → 5.54.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 (201) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/README.md +11 -13
  3. package/claude/.claude-plugin/plugin.json +1 -1
  4. package/claude/skills/canon-cli/SKILL.md +5 -8
  5. package/claude/skills/context-fold/REQUIREMENT.md +0 -1
  6. package/claude/skills/design-identity/REQUIREMENT.md +2 -2
  7. package/claude/skills/design-identity/SKILL.md +6 -6
  8. package/claude/skills/design-record/REQUIREMENT.md +2 -2
  9. package/claude/skills/design-record/SKILL.md +4 -4
  10. package/claude/skills/design-record/references/folder.md +1 -1
  11. package/claude/skills/design-taste/REQUIREMENT.md +1 -1
  12. package/claude/skills/design-taste/references/kinds.md +0 -1
  13. package/claude/skills/draw-figure/REQUIREMENT.md +3 -4
  14. package/claude/skills/draw-figure/SKILL.md +5 -6
  15. package/claude/skills/draw-figure/references/figures.md +0 -1
  16. package/claude/skills/draw-figure/references/hand-drawn.md +1 -1
  17. package/claude/skills/pick-by-eye/REQUIREMENT.md +4 -5
  18. package/claude/skills/pick-by-eye/SKILL.md +34 -41
  19. package/claude/skills/pick-by-eye/references/board.md +42 -0
  20. package/claude/skills/pick-by-eye/references/live-arms.md +3 -3
  21. package/claude/skills/plan-groundwork/SKILL.md +1 -1
  22. package/claude/skills/teach-craft/REQUIREMENT.md +30 -0
  23. package/claude/skills/teach-craft/SKILL.md +70 -0
  24. package/claude/skills/teach-craft/references/adopted.md +113 -0
  25. package/claude/skills/teach-craft/references/lesson-craft.md +60 -0
  26. package/claude/skills/{teach-workspace → teach-craft}/references/pedagogy.md +41 -6
  27. package/docs/agents/audits.md +0 -1
  28. package/docs/agents/install-and-sync.md +0 -8
  29. package/docs/target/migrations.md +16 -2
  30. package/docs/target/projects.md +1 -1
  31. package/docs/workflow/parallel-features.md +1 -1
  32. package/docs/workflow/skill-map-on-request.md +10 -22
  33. package/docs/workflow/skill-map.md +11 -14
  34. package/docs/workflow/visual-design-workflow.md +1 -4
  35. package/governance/detect.toml +1 -6
  36. package/governance/renames.toml +0 -1
  37. package/package.json +2 -8
  38. package/scripts/core/regen-web-previews.ts +2 -67
  39. package/src/audits/catalog.ts +0 -1
  40. package/src/browser/engine.ts +3 -6
  41. package/src/capture/render.ts +1 -1
  42. package/src/claude/cases/authoring.ts +0 -12
  43. package/src/claude/cases/misc.ts +0 -22
  44. package/src/claude/cases/workflow.ts +2 -38
  45. package/src/claude/skills-audit.ts +1 -1
  46. package/src/cli/help.ts +0 -10
  47. package/src/cli.ts +0 -8
  48. package/src/commands/design.ts +16 -315
  49. package/src/commands/records.ts +0 -1
  50. package/src/commands/serve.ts +2 -2
  51. package/src/commands/sync.ts +4 -5
  52. package/src/design/components.ts +8 -1514
  53. package/src/design/css.ts +5 -6
  54. package/src/design/fonts.ts +3 -5
  55. package/src/design/regen.ts +5 -32
  56. package/src/design/render.ts +1 -1
  57. package/src/design/tokens.ts +3 -2
  58. package/src/driver/drive.ts +3 -4
  59. package/src/driver/steps.ts +2 -5
  60. package/src/gate/stages.ts +4 -10
  61. package/src/gov/audit.ts +1 -6
  62. package/src/inventory/walk.ts +1 -1
  63. package/src/markdown/scope.ts +6 -35
  64. package/src/records/validate.ts +4 -176
  65. package/src/sandbox/equivalence.ts +0 -5
  66. package/src/shipped/references.ts +1 -2
  67. package/src/sync/check.ts +4 -29
  68. package/src/sync/stamp.ts +6 -6
  69. package/src/sync/target.ts +1 -4
  70. package/tooling/claude/reference.md +1 -1
  71. package/tooling/claude/seeds/canon/DESIGN.md +1 -1
  72. package/claude/skills/canvas-board/REQUIREMENT.md +0 -35
  73. package/claude/skills/canvas-board/SKILL.md +0 -143
  74. package/claude/skills/canvas-board/references/canvas.md +0 -170
  75. package/claude/skills/draft-and-pick/REQUIREMENT.md +0 -26
  76. package/claude/skills/draft-and-pick/SKILL.md +0 -11
  77. package/claude/skills/draft-doc/REQUIREMENT.md +0 -26
  78. package/claude/skills/draft-doc/SKILL.md +0 -11
  79. package/claude/skills/draft-figure/REQUIREMENT.md +0 -26
  80. package/claude/skills/draft-figure/SKILL.md +0 -11
  81. package/claude/skills/draft-identity/REQUIREMENT.md +0 -26
  82. package/claude/skills/draft-identity/SKILL.md +0 -11
  83. package/claude/skills/draft-ready/REQUIREMENT.md +0 -26
  84. package/claude/skills/draft-ready/SKILL.md +0 -11
  85. package/claude/skills/draft-screencast/REQUIREMENT.md +0 -26
  86. package/claude/skills/draft-screencast/SKILL.md +0 -11
  87. package/claude/skills/draft-slides/REQUIREMENT.md +0 -26
  88. package/claude/skills/draft-slides/SKILL.md +0 -11
  89. package/claude/skills/make-deck/REQUIREMENT.md +0 -36
  90. package/claude/skills/make-deck/SKILL.md +0 -80
  91. package/claude/skills/make-deck/references/deck.md +0 -183
  92. package/claude/skills/read-frames/REQUIREMENT.md +0 -30
  93. package/claude/skills/read-frames/SKILL.md +0 -55
  94. package/claude/skills/record-screencast/REQUIREMENT.md +0 -35
  95. package/claude/skills/record-screencast/SKILL.md +0 -99
  96. package/claude/skills/script-screencast/REQUIREMENT.md +0 -34
  97. package/claude/skills/script-screencast/SKILL.md +0 -70
  98. package/claude/skills/script-screencast/references/beats-template.md +0 -119
  99. package/claude/skills/teach-workspace/REQUIREMENT.md +0 -34
  100. package/claude/skills/teach-workspace/SKILL.md +0 -196
  101. package/claude/skills/teach-workspace/references/glossary.md +0 -90
  102. package/claude/skills/teach-workspace/references/lesson-build.md +0 -106
  103. package/claude/skills/teach-workspace/references/lesson-craft.md +0 -135
  104. package/claude/skills/teach-workspace/references/promotion-fold.md +0 -35
  105. package/claude/skills/teach-workspace/references/promotion.md +0 -116
  106. package/claude/skills/teach-workspace/references/revisit.md +0 -28
  107. package/claude/skills/teach-workspace/references/teach.md +0 -211
  108. package/claude/skills/video-craft/REQUIREMENT.md +0 -35
  109. package/claude/skills/video-craft/SKILL.md +0 -96
  110. package/claude/skills/video-craft/references/adopted.md +0 -110
  111. package/governance/rules/ui/canvas.md +0 -13
  112. package/src/canvas/address.ts +0 -227
  113. package/src/canvas/arrange.ts +0 -66
  114. package/src/canvas/capture.ts +0 -391
  115. package/src/canvas/client/app.tsx +0 -188
  116. package/src/canvas/client/inspector/align-grid.tsx +0 -162
  117. package/src/canvas/client/inspector/color-field.tsx +0 -398
  118. package/src/canvas/client/inspector/color-inputs.tsx +0 -139
  119. package/src/canvas/client/inspector/color-picker.tsx +0 -668
  120. package/src/canvas/client/inspector/color-space.ts +0 -240
  121. package/src/canvas/client/inspector/field.tsx +0 -263
  122. package/src/canvas/client/inspector/fields.css +0 -763
  123. package/src/canvas/client/inspector/section.tsx +0 -27
  124. package/src/canvas/client/inspector/size-field.tsx +0 -69
  125. package/src/canvas/client/inspector/token-select.tsx +0 -109
  126. package/src/canvas/client/inspector/values.ts +0 -297
  127. package/src/canvas/client/inspector.tsx +0 -692
  128. package/src/canvas/client/keys.ts +0 -71
  129. package/src/canvas/client/layers.tsx +0 -118
  130. package/src/canvas/client/main.tsx +0 -71
  131. package/src/canvas/client/pages-panel.tsx +0 -212
  132. package/src/canvas/client/panel-handle.tsx +0 -90
  133. package/src/canvas/client/selection.tsx +0 -199
  134. package/src/canvas/client/shell.css +0 -762
  135. package/src/canvas/client/state.ts +0 -792
  136. package/src/canvas/client/surface.tsx +0 -803
  137. package/src/canvas/client/theme-panel.tsx +0 -55
  138. package/src/canvas/client/tools.tsx +0 -153
  139. package/src/canvas/content.ts +0 -781
  140. package/src/canvas/edit.ts +0 -575
  141. package/src/canvas/editing.ts +0 -203
  142. package/src/canvas/fit.ts +0 -238
  143. package/src/canvas/global.d.ts +0 -15
  144. package/src/canvas/history.ts +0 -116
  145. package/src/canvas/index.html +0 -20
  146. package/src/canvas/server.ts +0 -766
  147. package/src/canvas/tokens.ts +0 -221
  148. package/src/commands/canvas.ts +0 -1097
  149. package/src/commands/demo.ts +0 -542
  150. package/src/commands/slides.ts +0 -184
  151. package/src/commands/teach.ts +0 -1401
  152. package/src/demo/beats.ts +0 -135
  153. package/src/demo/compile.ts +0 -350
  154. package/src/demo/container.ts +0 -219
  155. package/src/demo/cursors.ts +0 -55
  156. package/src/demo/drive.ts +0 -442
  157. package/src/demo/pointer.ts +0 -178
  158. package/src/demo/theme.ts +0 -112
  159. package/src/demo/timeline.ts +0 -64
  160. package/src/design/adapter.ts +0 -59
  161. package/src/design/base.css +0 -203
  162. package/src/design/brand-favicon.ts +0 -18
  163. package/src/design/neutral.ts +0 -127
  164. package/src/design/project-fonts.ts +0 -392
  165. package/src/slides/convert/chart.ts +0 -165
  166. package/src/slides/convert/deck.ts +0 -244
  167. package/src/slides/convert/export.ts +0 -567
  168. package/src/slides/convert/master.ts +0 -198
  169. package/src/slides/convert/shapes.ts +0 -804
  170. package/src/slides/convert/svg.ts +0 -38
  171. package/src/slides/convert/walk.ts +0 -671
  172. package/src/slides/decks.ts +0 -110
  173. package/src/slides/open.ts +0 -18
  174. package/src/slides/package/fonts.ts +0 -301
  175. package/src/slides/package/motion.ts +0 -316
  176. package/src/slides/package/test-face.ts +0 -113
  177. package/src/teach/browser/compile.ts +0 -44
  178. package/src/teach/browser/dismiss.ts +0 -76
  179. package/src/teach/browser/focus-line.ts +0 -19
  180. package/src/teach/browser/glossary-filter.ts +0 -44
  181. package/src/teach/browser/head.ts +0 -30
  182. package/src/teach/browser/quiz.ts +0 -19
  183. package/src/teach/browser/reload.ts +0 -9
  184. package/src/teach/browser/sidebar.ts +0 -233
  185. package/src/teach/browser/theme.ts +0 -18
  186. package/src/teach/components/code.tsx +0 -24
  187. package/src/teach/components/heading.tsx +0 -11
  188. package/src/teach/components/list.tsx +0 -17
  189. package/src/teach/components/paragraph.tsx +0 -29
  190. package/src/teach/components/refs.tsx +0 -28
  191. package/src/teach/cross-references.ts +0 -78
  192. package/src/teach/fonts.ts +0 -16
  193. package/src/teach/highlight.ts +0 -71
  194. package/src/teach/html/jsx-dev-runtime.ts +0 -13
  195. package/src/teach/html/jsx-runtime.ts +0 -113
  196. package/src/teach/html/raw.ts +0 -28
  197. package/src/teach/lesson.ts +0 -178
  198. package/src/teach/nav.ts +0 -1337
  199. package/src/teach/render.ts +0 -240
  200. package/src/teach/workspace.ts +0 -1164
  201. package/src/teach/write-if-changed.ts +0 -17
@@ -1,188 +0,0 @@
1
- /** @jsxImportSource preact */
2
- import { effect } from '@preact/signals'
3
- import type { JSX } from 'preact'
4
- import { useLayoutEffect, useRef } from 'preact/hooks'
5
- import { Inspector } from '@/canvas/client/inspector'
6
- import { PagesPanel } from '@/canvas/client/pages-panel'
7
- import { PanelHandle } from '@/canvas/client/panel-handle'
8
- import {
9
- clampPanelWidth,
10
- currentPage,
11
- DEFAULT_PANEL_WIDTHS,
12
- focusFrame,
13
- type PanelWidths,
14
- panelsHidden,
15
- panelWidths,
16
- tokens,
17
- } from '@/canvas/client/state'
18
- import { Surface } from '@/canvas/client/surface'
19
-
20
- const SOURCE_LABEL = {
21
- toolkit: 'This toolkit',
22
- installed: 'Installed design',
23
- none: 'None',
24
- } as const
25
-
26
- function TokenDetails(): JSX.Element | null {
27
- const value = tokens.value
28
- if (!value) return null
29
- return (
30
- <section aria-labelledby="tokens-heading">
31
- <h2 id="tokens-heading" class="section-label">
32
- Tokens
33
- </h2>
34
- <p class="detail">{SOURCE_LABEL[value.source]}</p>
35
- {value.files && value.files.length > 0 ? (
36
- <ul class="files">
37
- {value.files.map((file) => (
38
- <li key={file} title={file}>
39
- <code>{file}</code>
40
- </li>
41
- ))}
42
- </ul>
43
- ) : null}
44
- {value.notice ? <p class="notice">{value.notice}</p> : null}
45
- </section>
46
- )
47
- }
48
-
49
- function PageDetails(): JSX.Element | null {
50
- const page = currentPage.value
51
- if (!page) return null
52
- const unplaced = page.frames.filter((frame) => !frame.placed).length
53
- return (
54
- <section aria-labelledby="page-heading">
55
- <h2 id="page-heading" class="section-label">
56
- Page
57
- </h2>
58
- <p class="detail" title={page.name}>
59
- {page.name}
60
- </p>
61
- <p class="detail-meta">
62
- {page.frames.length} {page.frames.length === 1 ? 'frame' : 'frames'}
63
- </p>
64
- {unplaced > 0 ? (
65
- <p class="notice">
66
- {unplaced} {unplaced === 1 ? 'frame has' : 'frames have'} no box in
67
- layout.json and sit in a default row.
68
- </p>
69
- ) : null}
70
- {page.layoutIssue === 'malformed' ? (
71
- <p class="notice" role="alert">
72
- layout.json does not parse, so every frame sits in a default row. Fix
73
- the file to restore their places.
74
- </p>
75
- ) : null}
76
- </section>
77
- )
78
- }
79
-
80
- const PANELS_KEY = 'canon-canvas-panels'
81
-
82
- interface StoredPanels extends PanelWidths {
83
- readonly hidden: boolean
84
- }
85
-
86
- function storedWidth(value: unknown, fallback: number): number {
87
- return typeof value === 'number' && Number.isFinite(value) ? value : fallback
88
- }
89
-
90
- /** What the last visit left, with anything unreadable read as the default. */
91
- function readStoredPanels(): StoredPanels {
92
- const fallback = { hidden: false, ...DEFAULT_PANEL_WIDTHS }
93
- try {
94
- const parsed: unknown = JSON.parse(localStorage.getItem(PANELS_KEY) ?? '{}')
95
- if (typeof parsed !== 'object' || parsed === null) return fallback
96
- const record = parsed as Record<string, unknown>
97
- return {
98
- hidden: record.hidden === true,
99
- left: storedWidth(record.left, fallback.left),
100
- right: storedWidth(record.right, fallback.right),
101
- }
102
- } catch {
103
- return fallback
104
- }
105
- }
106
-
107
- function storePanels(panels: StoredPanels): void {
108
- try {
109
- localStorage.setItem(PANELS_KEY, JSON.stringify(panels))
110
- } catch {
111
- /* A blocked store costs the remembered layout, nothing else. */
112
- }
113
- }
114
-
115
- /**
116
- * Holds both widths inside this window, the details panel giving way first,
117
- * since long layer names are what the pages panel widens for.
118
- */
119
- function fitWidths(widths: PanelWidths): PanelWidths {
120
- const right = clampPanelWidth(
121
- 'right',
122
- widths.right,
123
- window.innerWidth,
124
- widths,
125
- )
126
- const left = clampPanelWidth('left', widths.left, window.innerWidth, {
127
- ...widths,
128
- right,
129
- })
130
- return { left, right }
131
- }
132
-
133
- /**
134
- * Restores the panels the last visit left and stores each change, the way the
135
- * theme pick is kept. The read lands before the first paint, so a hidden
136
- * layout never flashes open. The widths are clamped on that read and on every
137
- * window resize, since a width kept from a wider window could squeeze the
138
- * surface out.
139
- */
140
- function usePanelPreference(): void {
141
- useLayoutEffect(() => {
142
- const stored = readStoredPanels()
143
- panelsHidden.value = stored.hidden
144
- panelWidths.value = fitWidths(stored)
145
- const handleResize = () => {
146
- const fitted = fitWidths(panelWidths.value)
147
- const { left, right } = panelWidths.value
148
- if (fitted.left !== left || fitted.right !== right) {
149
- panelWidths.value = fitted
150
- }
151
- }
152
- window.addEventListener('resize', handleResize)
153
- const stopStoring = effect(() =>
154
- storePanels({ hidden: panelsHidden.value, ...panelWidths.value }),
155
- )
156
- return () => {
157
- window.removeEventListener('resize', handleResize)
158
- stopStoring()
159
- }
160
- }, [])
161
- }
162
-
163
- export function App(): JSX.Element {
164
- const viewportRef = useRef<HTMLDivElement>(null)
165
- usePanelPreference()
166
- const { left, right } = panelWidths.value
167
- return (
168
- <div
169
- class={panelsHidden.value ? 'shell panels-hidden' : 'shell'}
170
- style={{ '--panel-left': `${left}px`, '--panel-right': `${right}px` }}
171
- >
172
- <PagesPanel
173
- onFocusFrame={(frame) => {
174
- const rect = viewportRef.current?.getBoundingClientRect()
175
- focusFrame(frame, rect?.width ?? 0, rect?.height ?? 0)
176
- }}
177
- />
178
- <PanelHandle side="left" controls="pages-panel" />
179
- <Surface viewportRef={viewportRef} />
180
- <aside id="details-panel" class="panel panel-right" aria-label="Details">
181
- <Inspector />
182
- <PageDetails />
183
- <TokenDetails />
184
- </aside>
185
- <PanelHandle side="right" controls="details-panel" />
186
- </div>
187
- )
188
- }
@@ -1,162 +0,0 @@
1
- /** @jsxImportSource preact */
2
- import type { JSX } from 'preact'
3
- import { useRef, useState } from 'preact/hooks'
4
-
5
- /** The value each third of an axis writes, start to end as the axis runs. */
6
- const POSITIONS = ['flex-start', 'center', 'flex-end'] as const
7
-
8
- const ROWS = ['top', 'middle', 'bottom'] as const
9
- const COLUMNS = ['left', 'center', 'right'] as const
10
-
11
- /**
12
- * Computed values that read as one of the three positions. A container left
13
- * at its defaults packs from the start, and stretched children do too, so
14
- * both show the start cell without stating it.
15
- */
16
- const READS: Readonly<Record<string, number>> = {
17
- normal: 0,
18
- stretch: 0,
19
- 'flex-start': 0,
20
- start: 0,
21
- 'self-start': 0,
22
- left: 0,
23
- center: 1,
24
- 'flex-end': 2,
25
- end: 2,
26
- 'self-end': 2,
27
- right: 2,
28
- }
29
-
30
- /** Values a container takes without stating a position, which a pick pins. */
31
- const IMPLIED = new Set(['normal', 'stretch'])
32
-
33
- export interface Alignment {
34
- readonly justifyContent: string
35
- readonly alignItems: string
36
- }
37
-
38
- interface AlignGridProps {
39
- /** The container's computed `flex-direction`, which decides the axes. */
40
- readonly direction: string
41
- readonly justifyContent: string
42
- readonly alignItems: string
43
- readonly isBusy: boolean
44
- readonly onPick: (alignment: Alignment) => void
45
- }
46
-
47
- function isRow(direction: string): boolean {
48
- return !direction.startsWith('column')
49
- }
50
-
51
- /**
52
- * The cell, as row then column on screen, that a container's alignment puts
53
- * its children in. A reversed main axis runs from the far edge, so its start
54
- * is the right or the bottom.
55
- */
56
- function cellOf(
57
- direction: string,
58
- justifyContent: string,
59
- alignItems: string,
60
- ): readonly [number, number] | undefined {
61
- const main = READS[justifyContent.trim()]
62
- const cross = READS[alignItems.trim()]
63
- if (main === undefined || cross === undefined) return undefined
64
- const along = direction.endsWith('reverse') ? 2 - main : main
65
- return isRow(direction) ? [cross, along] : [along, cross]
66
- }
67
-
68
- function alignmentOf(
69
- direction: string,
70
- row: number,
71
- column: number,
72
- ): Alignment {
73
- const [main, cross] = isRow(direction) ? [column, row] : [row, column]
74
- const along = direction.endsWith('reverse') ? 2 - main : main
75
- return {
76
- justifyContent: POSITIONS[along],
77
- alignItems: POSITIONS[cross],
78
- }
79
- }
80
-
81
- const KEY_STEPS: Readonly<Record<string, readonly [number, number]>> = {
82
- ArrowUp: [-1, 0],
83
- ArrowDown: [1, 0],
84
- ArrowLeft: [0, -1],
85
- ArrowRight: [0, 1],
86
- }
87
-
88
- /**
89
- * Nine cells placing a flex container's children, one radio group. The
90
- * arrow keys move focus inside the grid and stop at its edges, and a press
91
- * or Enter or Space picks, since each pick writes the frame twice.
92
- */
93
- export function AlignGrid({
94
- direction,
95
- justifyContent,
96
- alignItems,
97
- isBusy,
98
- onPick,
99
- }: AlignGridProps): JSX.Element {
100
- const checked = cellOf(direction, justifyContent, alignItems)
101
- const isImplied =
102
- IMPLIED.has(justifyContent.trim()) || IMPLIED.has(alignItems.trim())
103
- const [focus, setFocus] = useState<readonly [number, number]>(
104
- checked ?? [0, 0],
105
- )
106
- const cells = useRef<(HTMLButtonElement | null)[]>([])
107
-
108
- const handleKeyDown = (event: KeyboardEvent) => {
109
- const step = KEY_STEPS[event.key]
110
- if (!step) return
111
- event.preventDefault()
112
- const next = [
113
- Math.min(2, Math.max(0, focus[0] + step[0])),
114
- Math.min(2, Math.max(0, focus[1] + step[1])),
115
- ] as const
116
- setFocus(next)
117
- cells.current[next[0] * 3 + next[1]]?.focus()
118
- }
119
-
120
- return (
121
- <div
122
- class="align-grid"
123
- role="radiogroup"
124
- aria-label="Alignment"
125
- onKeyDown={handleKeyDown}
126
- >
127
- {ROWS.map((rowName, row) =>
128
- COLUMNS.map((columnName, column) => {
129
- const isChecked = checked?.[0] === row && checked[1] === column
130
- const isFocusable = focus[0] === row && focus[1] === column
131
- const name =
132
- rowName === 'middle' && columnName === 'center'
133
- ? 'center'
134
- : `${rowName} ${columnName}`
135
- return (
136
- <button
137
- key={name}
138
- ref={(node) => {
139
- cells.current[row * 3 + column] = node
140
- }}
141
- type="button"
142
- class="align-cell"
143
- role="radio"
144
- aria-label={name}
145
- aria-checked={isChecked}
146
- tabIndex={isFocusable ? 0 : -1}
147
- disabled={isBusy}
148
- onFocus={() => setFocus([row, column])}
149
- onClick={() => {
150
- if (!isChecked || isImplied) {
151
- onPick(alignmentOf(direction, row, column))
152
- }
153
- }}
154
- >
155
- <span class="align-dot" aria-hidden="true" />
156
- </button>
157
- )
158
- }),
159
- )}
160
- </div>
161
- )
162
- }