@heyramzi/ui 2.8.0 → 2.10.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.
- package/COMPONENTS.md +1 -1
- package/README.md +1 -1
- package/dist/agents/helpers.js +52 -0
- package/dist/agents/index.js +3 -0
- package/dist/agents/page-state.js +65 -0
- package/dist/agents/types.js +1 -0
- package/dist/agents/vendor/color.js +149 -0
- package/dist/agents/vendor/draw.js +548 -0
- package/dist/agents/vendor/engine.js +632 -0
- package/dist/agents/vendor/mesh.js +727 -0
- package/dist/agents/vendor/plastic.js +3273 -0
- package/dist/agents/vendor/presets.js +171 -0
- package/dist/agents/vendor/shapes.js +24 -0
- package/dist/agents/vendor/ticker.js +56 -0
- package/dist/agents/vendor/types.js +0 -0
- package/dist/agents/vendor/wear.js +1525 -0
- package/dist/ai/ai-button/index.js +2 -0
- package/dist/ai/confirmation/confirmation-context.svelte.js +12 -0
- package/dist/ai/confirmation/index.js +9 -0
- package/dist/ai/generation-progress/index.js +2 -0
- package/dist/ai/index.js +11 -0
- package/dist/ai/loading-state/index.js +3 -0
- package/dist/ai/prompt-input/index.js +6 -0
- package/dist/ai/reasoning/index.js +4 -0
- package/dist/ai/reasoning/reasoning-context.svelte.js +12 -0
- package/dist/ai/response/index.js +3 -0
- package/dist/ai/suggestion/index.js +3 -0
- package/dist/ai/thinking-dots/index.js +3 -0
- package/dist/ai/typing-dots/index.js +2 -0
- package/dist/ai/voice-waveform/index.js +3 -0
- package/dist/animations/text-swap.js +30 -0
- package/dist/brand/index.js +65 -0
- package/dist/canvas/card/resize.js +10 -0
- package/dist/canvas/edges/edge-path.js +284 -0
- package/dist/canvas/editor/context-menu.js +42 -0
- package/dist/canvas/editor/dispatch.svelte.js +157 -0
- package/dist/canvas/editor/editor-context.js +8 -0
- package/dist/canvas/editor/editor-mode.js +0 -0
- package/dist/canvas/editor/frame.js +87 -0
- package/dist/canvas/editor/hand-context.js +8 -0
- package/dist/canvas/editor/history-core.js +221 -0
- package/dist/canvas/editor/keymap.js +193 -0
- package/dist/canvas/editor/layout-actions.js +170 -0
- package/dist/canvas/editor/lock.js +65 -0
- package/dist/canvas/editor/rebase.js +279 -0
- package/dist/canvas/editor/style.js +174 -0
- package/dist/canvas/editor/text-field-context.js +8 -0
- package/dist/canvas/editor/z-order.js +82 -0
- package/dist/canvas/headless/alignment.js +20 -0
- package/dist/canvas/headless/break-apart-find.js +324 -0
- package/dist/canvas/headless/break-apart-pieces.js +74 -0
- package/dist/canvas/headless/break-apart-plan.js +378 -0
- package/dist/canvas/headless/break-apart-style.js +93 -0
- package/dist/canvas/headless/break-apart.js +206 -0
- package/dist/canvas/headless/canvas-cleanup.js +70 -0
- package/dist/canvas/headless/edge-anchors.js +134 -0
- package/dist/canvas/headless/edge-memo.js +28 -0
- package/dist/canvas/headless/edge-serialization.js +31 -0
- package/dist/canvas/headless/figure-geometry.js +331 -0
- package/dist/canvas/headless/fit-viewport.js +82 -0
- package/dist/canvas/headless/grid.js +96 -0
- package/dist/canvas/headless/icon-node.js +45 -0
- package/dist/canvas/headless/index.js +1 -0
- package/dist/canvas/headless/linkify.js +25 -0
- package/dist/canvas/headless/pen-marks.js +115 -0
- package/dist/canvas/headless/sketch.js +250 -0
- package/dist/canvas/headless/snap-guides.js +100 -0
- package/dist/canvas/headless/svg-figure.js +137 -0
- package/dist/canvas/headless/table-layout.js +161 -0
- package/dist/canvas/index.js +25 -0
- package/dist/canvas/lod/lod-mode.svelte.js +22 -0
- package/dist/canvas/lod/render-all.svelte.js +45 -0
- package/dist/canvas/ops/arrange.js +83 -0
- package/dist/canvas/ops/ops.js +318 -0
- package/dist/canvas/pen/colors.js +41 -0
- package/dist/canvas/pen/eraser.js +35 -0
- package/dist/canvas/pen/geometry.js +143 -0
- package/dist/canvas/pen/index.js +9 -0
- package/dist/canvas/pen/ops.js +15 -0
- package/dist/canvas/pen/pen-session.js +171 -0
- package/dist/canvas/pen/plugin.js +129 -0
- package/dist/canvas/pen/shapes.js +80 -0
- package/dist/canvas/pen/stroke-path.js +37 -0
- package/dist/canvas/pen/types.js +30 -0
- package/dist/canvas/pen/ui.js +20 -0
- package/dist/canvas/plugin.js +51 -0
- package/dist/canvas/screen/glyphs.js +24 -0
- package/dist/canvas/screen/labels.js +24 -0
- package/dist/canvas/screen/parts.js +140 -0
- package/dist/canvas/screen/plugin.js +71 -0
- package/dist/canvas/screen/types.js +44 -0
- package/dist/canvas/screen/ui.js +13 -0
- package/dist/canvas/test-utils.js +18 -0
- package/dist/canvas/types.js +0 -0
- package/dist/canvas/ui/forward-wheel.js +27 -0
- package/dist/canvas/ui/icons.js +133 -0
- package/dist/canvas/ui/place-panel.js +57 -0
- package/dist/canvas/ui/shortcut-tip.js +18 -0
- package/dist/canvas/ui/tools.js +411 -0
- package/dist/charts/dashboard/chart.js +1 -0
- package/dist/charts/dashboard/data-table.js +7 -0
- package/dist/charts/dashboard/index.js +13 -0
- package/dist/charts/dashboard/windows.js +5 -0
- package/dist/charts/edge-fade.js +7 -0
- package/dist/charts/hover-band.js +13 -0
- package/dist/charts/index.js +19 -0
- package/dist/charts/motion.js +15 -0
- package/dist/charts/primitives/chart-utils.js +22 -0
- package/dist/charts/primitives/index.js +4 -0
- package/dist/components/copy/clipboard.js +38 -0
- package/dist/components/copy/copied.svelte.js +26 -0
- package/dist/components/copy/index.js +3 -0
- package/dist/components/data-table/data-table.js +55 -0
- package/dist/components/data-table/index.js +7 -0
- package/dist/components/docs/index.js +3 -0
- package/dist/components/docs/scroll-spy.svelte.js +71 -0
- package/dist/components/field-row/index.js +1 -0
- package/dist/components/hold-to-confirm/index.js +1 -0
- package/dist/components/icon/index.js +1 -0
- package/dist/components/language-flag/index.js +1 -0
- package/dist/components/list-page/filter-section.js +4 -0
- package/dist/components/list-page/index.js +25 -0
- package/dist/components/list-page/list-table.js +5 -0
- package/dist/components/list-page/queue-rail.js +3 -0
- package/dist/components/list-page/section-host.js +8 -0
- package/dist/components/list-page/step.js +5 -0
- package/dist/components/list-page/types.js +0 -0
- package/dist/components/locale-switch/index.js +1 -0
- package/dist/components/mark/index.js +1 -0
- package/dist/components/open-in/index.js +1 -0
- package/dist/components/picker/index.js +3 -0
- package/dist/components/picker/trigger.js +33 -0
- package/dist/components/picker/types.js +0 -0
- package/dist/components/section-card/index.js +1 -0
- package/dist/components/section-header/index.js +2 -0
- package/dist/components/segmented/collapse.js +32 -0
- package/dist/components/segmented/index.js +8 -0
- package/dist/components/segmented/segmented.js +50 -0
- package/dist/components/star-rating-input/index.js +2 -0
- package/dist/components/svg/index.js +1 -0
- package/dist/components/table-view/index.js +1 -0
- package/dist/components/table-view/types.js +0 -0
- package/dist/components/tags-input/index.js +2 -0
- package/dist/components/tags-input/tags.js +90 -0
- package/dist/components/theme/index.js +3 -0
- package/dist/components/toolbar/index.js +3 -0
- package/dist/components/toolbar/toolbar-trigger.js +4 -0
- package/dist/editor/anchors.js +17 -0
- package/dist/editor/block-id.js +62 -0
- package/dist/editor/block-ops.js +105 -0
- package/dist/editor/doc-blocks.js +181 -0
- package/dist/editor/extensions.js +200 -0
- package/dist/editor/index.js +4 -0
- package/dist/editor/markdown-test-helpers.js +6 -0
- package/dist/editor/markdown.js +486 -0
- package/dist/editor/serializer.js +268 -0
- package/dist/editor/slash-items.js +104 -0
- package/dist/editor/youtube-url.js +27 -0
- package/dist/effects/animated-beam/index.js +1 -0
- package/dist/effects/animated-beam/path-calculator.svelte.js +42 -0
- package/dist/effects/animated-beam/types.js +0 -0
- package/dist/effects/border-beam/css.js +420 -0
- package/dist/effects/border-beam/presets.js +1792 -0
- package/dist/effects/border-beam/register-properties.js +39 -0
- package/dist/effects/border-beam/types.js +0 -0
- package/dist/effects/image-comparison/compare.js +4 -0
- package/dist/effects/image-reveal/index.js +1 -0
- package/dist/effects/image-reveal/types.js +0 -0
- package/dist/effects/magnetic/magnetic.js +54 -0
- package/dist/effects/reveal/index.js +4 -0
- package/dist/effects/reveal/observe.js +43 -0
- package/dist/effects/reveal/types.js +0 -0
- package/dist/effects/shader-gradient/color.js +34 -0
- package/dist/effects/shader-gradient/index.js +1 -0
- package/dist/effects/shader-gradient/renderer.js +320 -0
- package/dist/effects/shader-gradient/shaders.js +280 -0
- package/dist/effects/shader-gradient/types.js +0 -0
- package/dist/icons/apple-symbol-exports.js +126 -0
- package/dist/icons/sf-symbols.js +465 -0
- package/dist/icons/trades.js +34 -0
- package/dist/inbox/index.js +4 -0
- package/dist/inbox/logic.js +156 -0
- package/dist/inbox/types.js +46 -0
- package/dist/index.js +18 -0
- package/dist/lib/arrive.js +13 -0
- package/dist/lib/icon-types.js +0 -0
- package/dist/lib/initials.js +17 -0
- package/dist/lib/layout.js +1 -0
- package/dist/lib/panel.js +3 -0
- package/dist/lib/result.js +26 -0
- package/dist/lib/sliding-pill.js +45 -0
- package/dist/lib/theme-transition.js +53 -0
- package/dist/lib/tone.js +32 -0
- package/dist/lib/utils.js +5 -0
- package/dist/onboarding/define-tours.js +28 -0
- package/dist/onboarding/index.js +4 -0
- package/dist/onboarding/onboarding.svelte.js +15 -0
- package/dist/onboarding/pick.js +16 -0
- package/dist/onboarding/stores.js +50 -0
- package/dist/onboarding/types.js +1 -0
- package/dist/onboarding/wait.js +25 -0
- package/dist/panel/index.js +1 -0
- package/dist/panel/side-panel-types.js +0 -0
- package/dist/record/demo-data.js +512 -0
- package/dist/record/fields.js +148 -0
- package/dist/record/format.js +97 -0
- package/dist/record/gutter.js +1 -0
- package/dist/record/index.js +15 -0
- package/dist/record/kinds.js +110 -0
- package/dist/record/logic.js +255 -0
- package/dist/record/types.js +52 -0
- package/dist/shadcn/accordion/index.js +5 -0
- package/dist/shadcn/alert/index.js +5 -0
- package/dist/shadcn/alert-dialog/index.js +12 -0
- package/dist/shadcn/attachment/index.js +10 -0
- package/dist/shadcn/avatar/index.js +7 -0
- package/dist/shadcn/badge/index.js +2 -0
- package/dist/shadcn/breadcrumb/index.js +8 -0
- package/dist/shadcn/bubble/index.js +5 -0
- package/dist/shadcn/button/index.js +2 -0
- package/dist/shadcn/calendar/index.js +19 -0
- package/dist/shadcn/card/index.js +8 -0
- package/dist/shadcn/checkbox/index.js +2 -0
- package/dist/shadcn/code-block/index.js +9 -0
- package/dist/shadcn/collapsible/index.js +4 -0
- package/dist/shadcn/command/index.js +13 -0
- package/dist/shadcn/context-menu/index.js +17 -0
- package/dist/shadcn/dialog/index.js +11 -0
- package/dist/shadcn/dropdown-menu/index.js +19 -0
- package/dist/shadcn/dropdown-menu/menu-item.js +23 -0
- package/dist/shadcn/empty/index.js +7 -0
- package/dist/shadcn/field/index.js +12 -0
- package/dist/shadcn/hooks/highlighter.js +92 -0
- package/dist/shadcn/hooks/is-mobile.svelte.js +7 -0
- package/dist/shadcn/hooks/use-highlighted-code.svelte.js +65 -0
- package/dist/shadcn/hover-card/index.js +5 -0
- package/dist/shadcn/input/index.js +3 -0
- package/dist/shadcn/input-otp/index.js +5 -0
- package/dist/shadcn/kbd/index.js +3 -0
- package/dist/shadcn/label/index.js +2 -0
- package/dist/shadcn/marker/index.js +4 -0
- package/dist/shadcn/message/index.js +7 -0
- package/dist/shadcn/message-scroller/index.js +8 -0
- package/dist/shadcn/popover/index.js +9 -0
- package/dist/shadcn/progress/index.js +2 -0
- package/dist/shadcn/progress/tone.js +11 -0
- package/dist/shadcn/radio-group/index.js +3 -0
- package/dist/shadcn/scroll-area/index.js +3 -0
- package/dist/shadcn/select/index.js +12 -0
- package/dist/shadcn/separator/index.js +2 -0
- package/dist/shadcn/sheet/index.js +11 -0
- package/dist/shadcn/sidebar/constants.js +6 -0
- package/dist/shadcn/sidebar/context.svelte.js +38 -0
- package/dist/shadcn/sidebar/index.js +25 -0
- package/dist/shadcn/skeleton/index.js +2 -0
- package/dist/shadcn/slider/index.js +2 -0
- package/dist/shadcn/sonner/index.js +1 -0
- package/dist/shadcn/spinner/index.js +1 -0
- package/dist/shadcn/switch/index.js +2 -0
- package/dist/shadcn/table/index.js +9 -0
- package/dist/shadcn/tabs/index.js +5 -0
- package/dist/shadcn/textarea/index.js +2 -0
- package/dist/shadcn/toggle/index.js +3 -0
- package/dist/shadcn/toggle-group/index.js +3 -0
- package/dist/shadcn/tooltip/context.js +8 -0
- package/dist/shadcn/tooltip/index.js +6 -0
- package/dist/shadcn/trace/index.js +9 -0
- package/dist/slides/bridges.js +66 -0
- package/dist/slides/deck-controller.svelte.js +221 -0
- package/dist/slides/export/capture.js +81 -0
- package/dist/slides/export/ffmpeg.js +85 -0
- package/dist/slides/export/index.js +4 -0
- package/dist/slides/export/launch.js +8 -0
- package/dist/slides/export/pdf.js +78 -0
- package/dist/slides/export/types.js +0 -0
- package/dist/slides/index.js +7 -0
- package/dist/slides/labels.js +26 -0
- package/dist/slides/layout.js +47 -0
- package/dist/slides/model.js +9 -0
- package/dist/slides/navigation.js +89 -0
- package/dist/slides/types.js +6 -0
- package/dist/status/define-statuses.js +16 -0
- package/dist/status/index.js +4 -0
- package/dist/status/status-types.js +0 -0
- package/dist/test-setup.js +26 -0
- package/dist/thread/index.js +3 -0
- package/dist/thread/logic.js +94 -0
- package/dist/thread/types.js +23 -0
- package/dist/work/board-order.js +109 -0
- package/dist/work/dates.js +19 -0
- package/dist/work/detail/detail-types.js +20 -0
- package/dist/work/docs/edited.js +39 -0
- package/dist/work/docs/index.js +7 -0
- package/dist/work/docs/labels.js +38 -0
- package/dist/work/docs/menu.js +121 -0
- package/dist/work/docs/outline.js +39 -0
- package/dist/work/gantt/logic.js +260 -0
- package/dist/work/inbox/inbox-logic.js +94 -0
- package/dist/work/inbox/inbox-statuses.js +86 -0
- package/dist/work/inbox/inbox-types.js +0 -0
- package/dist/work/inbox/index.js +1 -0
- package/dist/work/index.js +21 -0
- package/dist/work/kanban-drag.js +25 -0
- package/dist/work/kanban-types.js +0 -0
- package/dist/work/presets/sales.js +35 -0
- package/dist/work/reorder.js +10 -0
- package/dist/work/task-types.js +0 -0
- package/dist/work/time/duration.js +60 -0
- package/dist/work/time/time-types.js +25 -0
- package/dist/work/use-kanban-dnd.svelte.js +128 -0
- package/package.json +102 -76
- package/src/agents/vendor/draw.ts +4 -4
- package/src/canvas/headless/canvas-cleanup.test.ts +1 -1
- package/src/canvas/ops/ops.ts +1 -1
- package/src/charts/area-chart.svelte +11 -1
- package/src/charts/bar-chart.svelte +18 -3
- package/src/charts/line-chart.svelte +11 -1
- package/src/components/data-table/data-table.ts +4 -5
- package/src/components/data-table/pagination.svelte +5 -3
- package/src/components/docs/on-this-page.svelte +82 -5
- package/src/components/docs/scroll-spy.svelte.ts +6 -1
- package/src/components/list-page/detail-header.svelte +7 -3
- package/src/components/list-page/empty-state.svelte +3 -1
- package/src/components/list-page/filter-popover.svelte +2 -2
- package/src/components/list-page/rail-row.svelte +5 -2
- package/src/components/mark/mark.svelte +2 -1
- package/src/components/section-card/section-card.svelte +3 -1
- package/src/components/section-header/section-header.svelte +5 -5
- package/src/components/segmented/segment.svelte +1 -1
- package/src/components/table-view/table-view.svelte +6 -1
- package/src/components/tags-input/tags-input.svelte +1 -1
- package/src/components/toolbar/toolbar-trigger.ts +8 -2
- package/src/components/toolbar/toolbar.svelte +1 -1
- package/src/editor/anchors.ts +28 -0
- package/src/editor/doc-blocks.ts +168 -0
- package/src/editor/doc-page.css +389 -0
- package/src/editor/editor.svelte +47 -5
- package/src/editor/extensions.ts +26 -2
- package/src/editor/markdown.ts +27 -2
- package/src/editor/slash-items.ts +18 -0
- package/src/icons/trades.ts +1 -1
- package/src/inbox/README.md +6 -4
- package/src/inbox/inbox.test.ts +1 -1
- package/src/inbox/index.ts +2 -2
- package/src/inbox/logic.ts +29 -5
- package/src/inbox/thread-inbox.svelte +219 -92
- package/src/inbox/types.ts +27 -1
- package/src/lib/initials.test.ts +25 -0
- package/src/lib/initials.ts +29 -0
- package/src/modules.test.ts +4 -64
- package/src/panel/README.md +1 -1
- package/src/record/README.md +1 -1
- package/src/record/demo-data.ts +4 -4
- package/src/record/info-list.svelte +5 -4
- package/src/record/next-up.svelte +1 -1
- package/src/record/project-list.svelte +1 -1
- package/src/record/record-demo.svelte +2 -2
- package/src/record/steps-rail.svelte +3 -3
- package/src/shadcn/badge/badge.svelte +1 -1
- package/src/shadcn/card/card-title.svelte +1 -5
- package/src/shadcn/empty/empty-description.svelte +1 -1
- package/src/shadcn/progress/progress.svelte +8 -1
- package/src/shadcn/table/table-cell.svelte +10 -2
- package/src/status/README.md +1 -1
- package/src/thread/README.md +2 -0
- package/src/thread/index.ts +9 -1
- package/src/thread/logic.ts +33 -3
- package/src/thread/thread-body.svelte +37 -0
- package/src/thread/thread-events.svelte +30 -0
- package/src/thread/thread.svelte +74 -59
- package/src/thread/types.ts +21 -0
- package/src/{tasks → work}/README.md +11 -8
- package/src/{tasks → work}/detail/task-thread.svelte +8 -15
- package/src/work/docs/doc-editor-page.svelte +194 -0
- package/src/work/docs/doc-menu.svelte +333 -0
- package/src/work/docs/docs-demo.svelte +227 -0
- package/src/work/docs/edited-chip.svelte +125 -0
- package/src/work/docs/edited.ts +54 -0
- package/src/work/docs/index.ts +38 -0
- package/src/work/docs/labels.ts +70 -0
- package/src/work/docs/menu.ts +127 -0
- package/src/work/docs/outline.ts +60 -0
- package/src/{tasks → work}/gantt/gantt-group-row.svelte +1 -1
- package/src/{tasks → work}/inbox/inbox-card.svelte +113 -50
- package/src/work/inbox/inbox-logic.ts +98 -0
- package/src/work/inbox/inbox-trace.svelte +58 -0
- package/src/{tasks → work}/inbox/inbox-types.ts +2 -0
- package/src/{tasks → work}/index.ts +0 -10
- package/src/{tasks → work}/kanban-board.svelte +1 -1
- package/src/{tasks → work}/task-list.svelte +1 -1
- package/src/{tasks → work}/time/time-tracker.svelte +2 -5
- package/src/tasks/inbox/inbox-logic.ts +0 -21
- package/src/tasks/inbox/inbox-trace.svelte +0 -51
- /package/src/{tasks → work}/ambient.d.ts +0 -0
- /package/src/{tasks → work}/board-order.ts +0 -0
- /package/src/{tasks → work}/dates.ts +0 -0
- /package/src/{tasks → work}/demo.svelte +0 -0
- /package/src/{tasks → work}/detail/detail-demo.svelte +0 -0
- /package/src/{tasks → work}/detail/detail-types.ts +0 -0
- /package/src/{tasks → work}/detail/task-chip.svelte +0 -0
- /package/src/{tasks → work}/detail/task-detail.svelte +0 -0
- /package/src/{tasks → work}/detail/task-property.svelte +0 -0
- /package/src/{tasks → work}/gantt/gantt-bar.svelte +0 -0
- /package/src/{tasks → work}/gantt/gantt-grid.svelte +0 -0
- /package/src/{tasks → work}/gantt/gantt-header.svelte +0 -0
- /package/src/{tasks → work}/gantt/gantt-task-row.svelte +0 -0
- /package/src/{tasks → work}/gantt/gantt.css +0 -0
- /package/src/{tasks → work}/gantt/gantt.test.ts +0 -0
- /package/src/{tasks → work}/gantt/logic.test.ts +0 -0
- /package/src/{tasks → work}/gantt/logic.ts +0 -0
- /package/src/{tasks → work}/inbox/inbox-draft.svelte +0 -0
- /package/src/{tasks → work}/inbox/inbox-statuses.ts +0 -0
- /package/src/{tasks → work}/inbox/index.ts +0 -0
- /package/src/{tasks → work}/kanban-column.svelte +0 -0
- /package/src/{tasks → work}/kanban-drag.ts +0 -0
- /package/src/{tasks → work}/kanban-types.ts +0 -0
- /package/src/{tasks → work}/presets/sales.ts +0 -0
- /package/src/{tasks → work}/reorder.ts +0 -0
- /package/src/{tasks → work}/task-gantt.svelte +0 -0
- /package/src/{tasks → work}/task-types.ts +0 -0
- /package/src/{tasks → work}/time/duration.ts +0 -0
- /package/src/{tasks → work}/time/time-chip.svelte +0 -0
- /package/src/{tasks → work}/time/time-dot.svelte +0 -0
- /package/src/{tasks → work}/time/time-ring.svelte +0 -0
- /package/src/{tasks → work}/time/time-types.ts +0 -0
- /package/src/{tasks → work}/use-kanban-dnd.svelte.ts +0 -0
package/src/thread/thread.svelte
CHANGED
|
@@ -2,15 +2,25 @@
|
|
|
2
2
|
import type { Snippet } from "svelte";
|
|
3
3
|
import { ArrowBendDownRight, Check, MapPin, PencilSimple, Trash } from "phosphor-svelte";
|
|
4
4
|
import { cn } from "../lib/utils.js";
|
|
5
|
+
import { initial } from "../lib/initials.js";
|
|
5
6
|
import { AgentAvatar } from "../agents/index.js";
|
|
6
|
-
import { TONE_CLASS } from "../lib/tone.js";
|
|
7
7
|
import RichRenderer from "../editor/renderer.svelte";
|
|
8
8
|
import { Skeleton } from "../shadcn/skeleton/index.js";
|
|
9
|
-
import
|
|
10
|
-
import
|
|
9
|
+
import ThreadBody from "./thread-body.svelte";
|
|
10
|
+
import ThreadEvents from "./thread-events.svelte";
|
|
11
|
+
import {
|
|
12
|
+
buildThread,
|
|
13
|
+
fillCount,
|
|
14
|
+
interleave,
|
|
15
|
+
resolveThreadLabels,
|
|
16
|
+
resolvedCount,
|
|
17
|
+
} from "./logic.js";
|
|
18
|
+
import type { ThreadComment, ThreadEvent, ThreadLabels, ThreadPost } from "./types.js";
|
|
11
19
|
|
|
12
20
|
interface Props {
|
|
13
21
|
comments: ThreadComment[];
|
|
22
|
+
/** Status moves, assignments and the like, one quiet line each between the comments. */
|
|
23
|
+
events?: ThreadEvent[];
|
|
14
24
|
/** Rows still on their way. Draws skeleton rows in place of the thread. */
|
|
15
25
|
loading?: boolean;
|
|
16
26
|
labels?: Partial<ThreadLabels>;
|
|
@@ -22,6 +32,10 @@
|
|
|
22
32
|
anchorChip?: Snippet<[ThreadComment]>;
|
|
23
33
|
/** How a timestamp reads. Defaults to a short date. */
|
|
24
34
|
when?: (comment: ThreadComment) => string;
|
|
35
|
+
/** How an event's time reads. Defaults to a short date. */
|
|
36
|
+
whenEvent?: (event: ThreadEvent) => string;
|
|
37
|
+
/** The locale the default times read in. */
|
|
38
|
+
locale?: string;
|
|
25
39
|
/** Returns false to keep the draft. Without it no composer shows. */
|
|
26
40
|
onPost?: (post: ThreadPost) => void | boolean | Promise<void | boolean>;
|
|
27
41
|
onEdit?: (comment: ThreadComment, body: string) => void | Promise<void>;
|
|
@@ -37,13 +51,15 @@
|
|
|
37
51
|
|
|
38
52
|
let {
|
|
39
53
|
comments,
|
|
54
|
+
events = [],
|
|
55
|
+
locale = "en-GB",
|
|
40
56
|
loading = false,
|
|
41
57
|
labels: labelOverrides,
|
|
42
58
|
avatar,
|
|
43
59
|
attachments,
|
|
44
60
|
anchorChip,
|
|
45
|
-
when = (comment) =>
|
|
46
|
-
|
|
61
|
+
when = (comment) => shortDate(comment.createdAt),
|
|
62
|
+
whenEvent = (event) => shortDate(event.at),
|
|
47
63
|
onPost,
|
|
48
64
|
onEdit,
|
|
49
65
|
onDelete,
|
|
@@ -58,6 +74,11 @@
|
|
|
58
74
|
let resolved = $derived(resolvedCount(nodes));
|
|
59
75
|
let showResolved = $state(false);
|
|
60
76
|
let shown = $derived(showResolved ? nodes : nodes.filter((node) => !node.comment.resolved));
|
|
77
|
+
let items = $derived(interleave(shown, events));
|
|
78
|
+
|
|
79
|
+
function shortDate(at: string): string {
|
|
80
|
+
return new Intl.DateTimeFormat(locale, { month: "short", day: "numeric" }).format(new Date(at));
|
|
81
|
+
}
|
|
61
82
|
|
|
62
83
|
let draft = $state("");
|
|
63
84
|
let replyTo = $state<string | null>(null);
|
|
@@ -101,10 +122,6 @@
|
|
|
101
122
|
if (!body || body === comment.body) return;
|
|
102
123
|
await onEdit?.(comment, body);
|
|
103
124
|
}
|
|
104
|
-
|
|
105
|
-
function initial(name: string): string {
|
|
106
|
-
return name.trim().charAt(0).toLocaleUpperCase() || "?";
|
|
107
|
-
}
|
|
108
125
|
</script>
|
|
109
126
|
|
|
110
127
|
{#snippet composer(
|
|
@@ -164,14 +181,7 @@
|
|
|
164
181
|
<div class="flex min-h-6 flex-wrap items-center gap-x-2">
|
|
165
182
|
<span class="truncate text-[13px] font-medium">{comment.author.name}</span>
|
|
166
183
|
{#if comment.author.kind === "agent"}
|
|
167
|
-
<span
|
|
168
|
-
class={cn(
|
|
169
|
-
"inline-flex h-5 items-center rounded-sm border px-1.5 text-xs font-medium",
|
|
170
|
-
TONE_CLASS.accent,
|
|
171
|
-
)}
|
|
172
|
-
>
|
|
173
|
-
{labels.agent}
|
|
174
|
-
</span>
|
|
184
|
+
<span class="sr-only">{labels.agent}</span>
|
|
175
185
|
{/if}
|
|
176
186
|
<span class="text-xs text-muted-foreground tabular-nums">{when(comment)}</span>
|
|
177
187
|
{#if comment.edited}
|
|
@@ -254,7 +264,7 @@
|
|
|
254
264
|
{:else if comment.content}
|
|
255
265
|
<div class="text-sm leading-relaxed"><RichRenderer content={comment.content} /></div>
|
|
256
266
|
{:else}
|
|
257
|
-
<
|
|
267
|
+
<ThreadBody text={comment.body} more={labels.showMore} less={labels.showLess} />
|
|
258
268
|
{/if}
|
|
259
269
|
|
|
260
270
|
{@render attachments?.(comment)}
|
|
@@ -289,49 +299,54 @@
|
|
|
289
299
|
</li>
|
|
290
300
|
{/each}
|
|
291
301
|
</ol>
|
|
292
|
-
{:else if
|
|
302
|
+
{:else if items.length > 0}
|
|
293
303
|
<ol class="flex flex-col gap-4">
|
|
294
|
-
{#each
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
<li>{@render row(reply, false)}</li>
|
|
307
|
-
{/each}
|
|
308
|
-
</ol>
|
|
309
|
-
{/if}
|
|
310
|
-
{#if onPost && !node.comment.resolved}
|
|
311
|
-
{#if replyTo === node.comment.id}
|
|
312
|
-
<div class="ms-9">
|
|
313
|
-
{@render composer(
|
|
314
|
-
replyDraft,
|
|
315
|
-
labels.replyPlaceholder,
|
|
316
|
-
sendReply,
|
|
317
|
-
(next) => (replyDraft = next),
|
|
318
|
-
true,
|
|
319
|
-
)}
|
|
320
|
-
</div>
|
|
321
|
-
{:else}
|
|
322
|
-
<button
|
|
323
|
-
type="button"
|
|
324
|
-
class="thread-button ms-9 flex w-fit items-center gap-1.5"
|
|
325
|
-
onclick={() => {
|
|
326
|
-
replyTo = node.comment.id;
|
|
327
|
-
replyDraft = "";
|
|
328
|
-
}}
|
|
329
|
-
>
|
|
330
|
-
<ArrowBendDownRight class="size-3.5" aria-hidden="true" />{labels.reply}
|
|
331
|
-
</button>
|
|
304
|
+
{#each items as item (item.key)}
|
|
305
|
+
{#if item.type === "events"}
|
|
306
|
+
<li><ThreadEvents events={item.events} when={whenEvent} /></li>
|
|
307
|
+
{:else}
|
|
308
|
+
{@const node = item.node}
|
|
309
|
+
<li
|
|
310
|
+
class={cn("flex flex-col gap-3", node.comment.resolved && "opacity-60")}
|
|
311
|
+
data-resolved={node.comment.resolved || undefined}
|
|
312
|
+
>
|
|
313
|
+
{@render row(node.comment, true)}
|
|
314
|
+
{#if node.comment.resolved}
|
|
315
|
+
<span class="ms-9 text-xs text-muted-foreground">{labels.resolved}</span>
|
|
332
316
|
{/if}
|
|
333
|
-
|
|
334
|
-
|
|
317
|
+
{#if node.replies.length > 0}
|
|
318
|
+
<ol class="ms-3 flex flex-col gap-3 border-s border-border ps-6">
|
|
319
|
+
{#each node.replies as reply (reply.id)}
|
|
320
|
+
<li>{@render row(reply, false)}</li>
|
|
321
|
+
{/each}
|
|
322
|
+
</ol>
|
|
323
|
+
{/if}
|
|
324
|
+
{#if onPost && !node.comment.resolved}
|
|
325
|
+
{#if replyTo === node.comment.id}
|
|
326
|
+
<div class="ms-9">
|
|
327
|
+
{@render composer(
|
|
328
|
+
replyDraft,
|
|
329
|
+
labels.replyPlaceholder,
|
|
330
|
+
sendReply,
|
|
331
|
+
(next) => (replyDraft = next),
|
|
332
|
+
true,
|
|
333
|
+
)}
|
|
334
|
+
</div>
|
|
335
|
+
{:else}
|
|
336
|
+
<button
|
|
337
|
+
type="button"
|
|
338
|
+
class="thread-button ms-9 flex w-fit items-center gap-1.5"
|
|
339
|
+
onclick={() => {
|
|
340
|
+
replyTo = node.comment.id;
|
|
341
|
+
replyDraft = "";
|
|
342
|
+
}}
|
|
343
|
+
>
|
|
344
|
+
<ArrowBendDownRight class="size-3.5" aria-hidden="true" />{labels.reply}
|
|
345
|
+
</button>
|
|
346
|
+
{/if}
|
|
347
|
+
{/if}
|
|
348
|
+
</li>
|
|
349
|
+
{/if}
|
|
335
350
|
{/each}
|
|
336
351
|
</ol>
|
|
337
352
|
{:else if !onPost}
|
package/src/thread/types.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { PhosphorIcon } from "../lib/icon-types.js";
|
|
2
|
+
|
|
1
3
|
export type ThreadAuthorKind = "user" | "agent";
|
|
2
4
|
|
|
3
5
|
export type ThreadAuthor = {
|
|
@@ -47,6 +49,21 @@ export type ThreadNode = {
|
|
|
47
49
|
replies: ThreadComment[];
|
|
48
50
|
};
|
|
49
51
|
|
|
52
|
+
/** Something that happened to the subject, drawn as one quiet line between comments. */
|
|
53
|
+
export type ThreadEvent = {
|
|
54
|
+
id: string;
|
|
55
|
+
/** The whole sentence, actor first: "Project Manager moved this from Open to In progress". */
|
|
56
|
+
title: string;
|
|
57
|
+
/** ISO timestamp. */
|
|
58
|
+
at: string;
|
|
59
|
+
icon?: PhosphorIcon;
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
/** The thread in time order: a conversation, or a run of events between two of them. */
|
|
63
|
+
export type ThreadItem =
|
|
64
|
+
| { type: "node"; key: string; node: ThreadNode }
|
|
65
|
+
| { type: "events"; key: string; events: ThreadEvent[] };
|
|
66
|
+
|
|
50
67
|
export type ThreadLabels = {
|
|
51
68
|
title: string;
|
|
52
69
|
empty: string;
|
|
@@ -68,6 +85,8 @@ export type ThreadLabels = {
|
|
|
68
85
|
hideResolved: string;
|
|
69
86
|
agent: string;
|
|
70
87
|
pinned: string;
|
|
88
|
+
showMore: string;
|
|
89
|
+
showLess: string;
|
|
71
90
|
};
|
|
72
91
|
|
|
73
92
|
export const DEFAULT_THREAD_LABELS: ThreadLabels = {
|
|
@@ -90,4 +109,6 @@ export const DEFAULT_THREAD_LABELS: ThreadLabels = {
|
|
|
90
109
|
hideResolved: "Hide resolved",
|
|
91
110
|
agent: "AI",
|
|
92
111
|
pinned: "Pinned",
|
|
112
|
+
showMore: "Show more",
|
|
113
|
+
showLess: "Show less",
|
|
93
114
|
};
|
|
@@ -1,9 +1,12 @@
|
|
|
1
|
-
# @heyramzi/ui/
|
|
1
|
+
# @heyramzi/ui/work
|
|
2
2
|
|
|
3
|
-
Svelte 5
|
|
4
|
-
|
|
5
|
-
Status badges, dots and icons come
|
|
6
|
-
[ui.heyramzi.com/
|
|
3
|
+
Svelte 5 work views: tasks and the docs that sit beside them. One array of
|
|
4
|
+
tasks shows as a drag-and-drop board, a grouped list or a gantt timeline, and
|
|
5
|
+
the same column config drives all three. Status badges, dots and icons come
|
|
6
|
+
from one map too. Live at [ui.heyramzi.com/work](https://ui.heyramzi.com/work).
|
|
7
|
+
|
|
8
|
+
Status badges and the side panel live in `@heyramzi/ui/status` and
|
|
9
|
+
`@heyramzi/ui/panel`.
|
|
7
10
|
|
|
8
11
|
Every view knows nothing about your data. You pass items and a few accessors,
|
|
9
12
|
and it hands back a change to persist. It is a subpath of `@heyramzi/ui` and builds on its primitives and on
|
|
@@ -24,7 +27,7 @@ isn't a drop target (an Overdue lane, say).
|
|
|
24
27
|
|
|
25
28
|
```svelte
|
|
26
29
|
<script lang="ts">
|
|
27
|
-
import { KanbanBoard, type KanbanMove } from "@heyramzi/ui/
|
|
30
|
+
import { KanbanBoard, type KanbanMove } from "@heyramzi/ui/work";
|
|
28
31
|
|
|
29
32
|
type Task = { id: string; column: string; title: string; order: string };
|
|
30
33
|
|
|
@@ -204,7 +207,7 @@ icon, so `ChartBarHorizontal` stands in.
|
|
|
204
207
|
`SidePanel` is a sheet for one record: a title, a description, status chips, doors
|
|
205
208
|
out to other tools (`openIn`), a copy-a-prompt `handoff`, a strip of `stats`, then
|
|
206
209
|
the body and an optional pinned `footer`. You pass the tools; the panel knows none.
|
|
207
|
-
Import it from `@heyramzi/ui/panel`, or from `@heyramzi/ui/
|
|
210
|
+
Import it from `@heyramzi/ui/panel`, or from `@heyramzi/ui/work` for now.
|
|
208
211
|
|
|
209
212
|
```svelte
|
|
210
213
|
<SidePanel
|
|
@@ -263,7 +266,7 @@ and fetches nothing. You pass entries in and persist what it hands back.
|
|
|
263
266
|
| `locale`, `labels`, `class` | | `labels` overrides any string in `DEFAULT_TIME_LABELS`. |
|
|
264
267
|
|
|
265
268
|
Alt+S starts and stops the timer. A screen reader hears the start, one update a
|
|
266
|
-
minute and the stop. Import it alone from `@heyramzi/ui/
|
|
269
|
+
minute and the stop. Import it alone from `@heyramzi/ui/work/time`.
|
|
267
270
|
|
|
268
271
|
For boards and lists: `TimeChip` (`minutes`, `estimate?`, `running?`) shows the
|
|
269
272
|
logged total, with a pulsing dot while a timer runs and a small ring against an
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { Snippet } from "svelte";
|
|
3
3
|
import { PencilSimple, Trash } from "phosphor-svelte";
|
|
4
|
-
import {
|
|
4
|
+
import { initial } from "../../lib/initials.js";
|
|
5
5
|
import { AgentAvatar } from "../../agents/index.js";
|
|
6
|
-
import { TONE_CLASS } from "../../lib/tone.js";
|
|
7
6
|
import { Skeleton } from "../../shadcn/skeleton/index.js";
|
|
8
7
|
import {
|
|
9
8
|
DEFAULT_TASK_DETAIL_LABELS,
|
|
@@ -22,6 +21,8 @@
|
|
|
22
21
|
avatar?: Snippet<[TaskComment]>;
|
|
23
22
|
/** How a timestamp reads. Defaults to a short date. */
|
|
24
23
|
when?: (comment: TaskComment) => string;
|
|
24
|
+
/** The locale the default times read in. */
|
|
25
|
+
locale?: string;
|
|
25
26
|
/** Returns false to keep the draft. Without it the composer is hidden. */
|
|
26
27
|
onSend?: (body: string) => void | boolean | Promise<void | boolean>;
|
|
27
28
|
onEdit?: (comment: TaskComment, body: string) => void | Promise<void>;
|
|
@@ -35,8 +36,11 @@
|
|
|
35
36
|
labels: labelOverrides,
|
|
36
37
|
agentAvatar,
|
|
37
38
|
avatar,
|
|
39
|
+
locale = "en-GB",
|
|
38
40
|
when = (comment) =>
|
|
39
|
-
new
|
|
41
|
+
new Intl.DateTimeFormat(locale, { month: "short", day: "numeric" }).format(
|
|
42
|
+
new Date(comment.createdAt),
|
|
43
|
+
),
|
|
40
44
|
onSend,
|
|
41
45
|
onEdit,
|
|
42
46
|
onDelete,
|
|
@@ -79,10 +83,6 @@
|
|
|
79
83
|
if (!body || body === comment.body) return;
|
|
80
84
|
await onEdit?.(comment, body);
|
|
81
85
|
}
|
|
82
|
-
|
|
83
|
-
function initial(name: string): string {
|
|
84
|
-
return name.trim().charAt(0).toLocaleUpperCase() || "?";
|
|
85
|
-
}
|
|
86
86
|
</script>
|
|
87
87
|
|
|
88
88
|
<section aria-label={labels.comments} class="flex flex-col gap-3">
|
|
@@ -132,14 +132,7 @@
|
|
|
132
132
|
<div class="flex h-6 items-center gap-2">
|
|
133
133
|
<span class="truncate text-[13px] font-medium">{comment.author}</span>
|
|
134
134
|
{#if comment.agent}
|
|
135
|
-
<span
|
|
136
|
-
class={cn(
|
|
137
|
-
"inline-flex h-5 items-center rounded-sm border px-1.5 text-xs font-medium",
|
|
138
|
-
TONE_CLASS.accent,
|
|
139
|
-
)}
|
|
140
|
-
>
|
|
141
|
-
{labels.ai}
|
|
142
|
-
</span>
|
|
135
|
+
<span class="sr-only">{labels.ai}</span>
|
|
143
136
|
{/if}
|
|
144
137
|
<span class="text-xs text-muted-foreground tabular-nums">{when(comment)}</span>
|
|
145
138
|
{#if comment.edited}
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
// =========================
|
|
3
|
+
// IMPORTS
|
|
4
|
+
// =========================
|
|
5
|
+
import type { Editor } from "@tiptap/core";
|
|
6
|
+
import { FileText } from "phosphor-svelte";
|
|
7
|
+
import type { Snippet } from "svelte";
|
|
8
|
+
import OnThisPage from "../../components/docs/on-this-page.svelte";
|
|
9
|
+
import { ScrollSpy } from "../../components/docs/scroll-spy.svelte.js";
|
|
10
|
+
import RichEditor from "../../editor/editor.svelte";
|
|
11
|
+
import { docLabels, type DocLabels } from "./labels.js";
|
|
12
|
+
import { outlineOfDoc, type OutlineHeading } from "./outline.js";
|
|
13
|
+
|
|
14
|
+
// =========================
|
|
15
|
+
// TYPES
|
|
16
|
+
// =========================
|
|
17
|
+
interface Props {
|
|
18
|
+
/** The title, edited in place. */
|
|
19
|
+
title: string;
|
|
20
|
+
/** The body as Tiptap JSON. Read once: wrap the page in `{#key doc.id}` to swap documents. */
|
|
21
|
+
content?: Record<string, unknown> | null;
|
|
22
|
+
onchange?: (json: Record<string, unknown>) => void;
|
|
23
|
+
ontitle?: (title: string) => void;
|
|
24
|
+
/** Focus the title on open: a doc that was just created. */
|
|
25
|
+
autofocusTitle?: boolean;
|
|
26
|
+
/** Parent icon, parent title › this doc. */
|
|
27
|
+
breadcrumb?: Snippet;
|
|
28
|
+
/** Sits beside the breadcrumb: the star, the `…` menu. */
|
|
29
|
+
menu?: Snippet;
|
|
30
|
+
/** Right side of the bar, before the actions: the "Edited" chip. */
|
|
31
|
+
meta?: Snippet;
|
|
32
|
+
/** Right side of the bar: copy link, subscribe. */
|
|
33
|
+
actions?: Snippet;
|
|
34
|
+
/** The tile above the title. Defaults to a document glyph. */
|
|
35
|
+
icon?: Snippet;
|
|
36
|
+
/** A heading's link was copied; show the toast here. */
|
|
37
|
+
oncopylink?: (url: string, id: string) => void;
|
|
38
|
+
labels?: Partial<DocLabels>;
|
|
39
|
+
/** The live editor, to focus it or read it. */
|
|
40
|
+
instance?: Editor | null;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// =========================
|
|
44
|
+
// PROPS
|
|
45
|
+
// =========================
|
|
46
|
+
let {
|
|
47
|
+
title = $bindable(""),
|
|
48
|
+
content = null,
|
|
49
|
+
onchange,
|
|
50
|
+
ontitle,
|
|
51
|
+
autofocusTitle = false,
|
|
52
|
+
breadcrumb,
|
|
53
|
+
menu,
|
|
54
|
+
meta,
|
|
55
|
+
actions,
|
|
56
|
+
icon,
|
|
57
|
+
oncopylink,
|
|
58
|
+
labels: labelOverrides,
|
|
59
|
+
instance = $bindable(null),
|
|
60
|
+
}: Props = $props();
|
|
61
|
+
|
|
62
|
+
// =========================
|
|
63
|
+
// STATE
|
|
64
|
+
// =========================
|
|
65
|
+
let scroller = $state<HTMLElement | null>(null);
|
|
66
|
+
let titleField = $state<HTMLTextAreaElement | null>(null);
|
|
67
|
+
let outline = $state<OutlineHeading[]>(outlineOfDoc(untrackedContent()));
|
|
68
|
+
const spy = new ScrollSpy();
|
|
69
|
+
|
|
70
|
+
// =========================
|
|
71
|
+
// DERIVED
|
|
72
|
+
// =========================
|
|
73
|
+
let t = $derived(docLabels(labelOverrides));
|
|
74
|
+
|
|
75
|
+
// =========================
|
|
76
|
+
// EFFECTS
|
|
77
|
+
// =========================
|
|
78
|
+
$effect(() => spy.attach(scroller, outline));
|
|
79
|
+
|
|
80
|
+
$effect(() => {
|
|
81
|
+
if (autofocusTitle) titleField?.focus();
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
// =========================
|
|
85
|
+
// FUNCTIONS
|
|
86
|
+
// =========================
|
|
87
|
+
// The first outline reads the prop once; later ones come from the editor's own changes.
|
|
88
|
+
function untrackedContent() {
|
|
89
|
+
return content;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function handleChange(json: Record<string, unknown>) {
|
|
93
|
+
outline = outlineOfDoc(json);
|
|
94
|
+
onchange?.(json);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function onTitleKey(event: KeyboardEvent) {
|
|
98
|
+
if (event.key === "Enter" || (event.key === "ArrowDown" && !event.shiftKey)) {
|
|
99
|
+
event.preventDefault();
|
|
100
|
+
instance?.commands.focus("start");
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
</script>
|
|
104
|
+
|
|
105
|
+
<!-- =========================== -->
|
|
106
|
+
<!-- MARKUP -->
|
|
107
|
+
<!-- =========================== -->
|
|
108
|
+
<div class="@container/doc flex h-full min-h-0 flex-col bg-background text-foreground">
|
|
109
|
+
<header
|
|
110
|
+
class="flex h-11 shrink-0 items-center gap-2 border-b border-border/70 px-3 @2xl/doc:px-4"
|
|
111
|
+
>
|
|
112
|
+
<div class="flex min-w-0 flex-1 items-center gap-1 text-[13px]">
|
|
113
|
+
{#if breadcrumb}{@render breadcrumb()}{/if}
|
|
114
|
+
{#if menu}{@render menu()}{/if}
|
|
115
|
+
</div>
|
|
116
|
+
<div class="flex shrink-0 items-center gap-1">
|
|
117
|
+
{#if meta}{@render meta()}{/if}
|
|
118
|
+
{#if actions}{@render actions()}{/if}
|
|
119
|
+
</div>
|
|
120
|
+
</header>
|
|
121
|
+
|
|
122
|
+
<div class="relative min-h-0 flex-1">
|
|
123
|
+
{#if outline.length > 0}
|
|
124
|
+
<!-- Wide: ticks in the left gutter, centred on the pane. -->
|
|
125
|
+
<div class="absolute top-1/2 left-1 z-20 hidden -translate-y-1/2 @4xl/doc:block">
|
|
126
|
+
<OnThisPage
|
|
127
|
+
variant="ticks"
|
|
128
|
+
items={outline}
|
|
129
|
+
active={spy.active}
|
|
130
|
+
label={t.outline}
|
|
131
|
+
onselect={(id) => spy.jump(id)}
|
|
132
|
+
/>
|
|
133
|
+
</div>
|
|
134
|
+
<!-- Narrow: the strip the reading pages use, since a phone has no gutter. -->
|
|
135
|
+
<div
|
|
136
|
+
class="absolute inset-x-0 top-0 z-20 border-b border-border/70 bg-background/95 backdrop-blur @4xl/doc:hidden"
|
|
137
|
+
>
|
|
138
|
+
<OnThisPage
|
|
139
|
+
variant="bar"
|
|
140
|
+
items={outline}
|
|
141
|
+
active={spy.active}
|
|
142
|
+
label={t.outline}
|
|
143
|
+
onselect={(id) => spy.jump(id)}
|
|
144
|
+
/>
|
|
145
|
+
</div>
|
|
146
|
+
{/if}
|
|
147
|
+
|
|
148
|
+
<div bind:this={scroller} class="thin-scrollbar h-full overflow-y-auto">
|
|
149
|
+
<div
|
|
150
|
+
class="mx-auto w-full max-w-[56rem] px-5 pb-40 @2xl/doc:px-8 {outline.length > 0
|
|
151
|
+
? 'pt-[3.75rem] @4xl/doc:pt-14'
|
|
152
|
+
: 'pt-8 @2xl/doc:pt-14'}"
|
|
153
|
+
>
|
|
154
|
+
<div
|
|
155
|
+
class="mb-4 flex size-12 items-center justify-center rounded-xl border border-border bg-muted/40 text-muted-foreground"
|
|
156
|
+
>
|
|
157
|
+
{#if icon}{@render icon()}{:else}<FileText size={22} aria-hidden="true" />{/if}
|
|
158
|
+
</div>
|
|
159
|
+
|
|
160
|
+
<textarea
|
|
161
|
+
bind:this={titleField}
|
|
162
|
+
bind:value={title}
|
|
163
|
+
oninput={() => ontitle?.(title)}
|
|
164
|
+
onkeydown={onTitleKey}
|
|
165
|
+
rows="1"
|
|
166
|
+
spellcheck="false"
|
|
167
|
+
aria-label={t.titlePlaceholder}
|
|
168
|
+
placeholder={t.titlePlaceholder}
|
|
169
|
+
class="doc-title mb-6 block w-full resize-none border-0 bg-transparent p-0 font-heading text-2xl leading-8 font-semibold tracking-tight text-foreground caret-brand outline-none focus-visible:shadow-none placeholder:text-muted-foreground/45"
|
|
170
|
+
></textarea>
|
|
171
|
+
|
|
172
|
+
<RichEditor
|
|
173
|
+
{content}
|
|
174
|
+
onchange={handleChange}
|
|
175
|
+
variant="page"
|
|
176
|
+
preset="full"
|
|
177
|
+
placeholder=""
|
|
178
|
+
minHeight="20rem"
|
|
179
|
+
copyLinkLabel={t.copyLink}
|
|
180
|
+
{oncopylink}
|
|
181
|
+
bind:instance
|
|
182
|
+
/>
|
|
183
|
+
</div>
|
|
184
|
+
</div>
|
|
185
|
+
</div>
|
|
186
|
+
</div>
|
|
187
|
+
|
|
188
|
+
<style>
|
|
189
|
+
/* The title grows with its text, so a long one wraps instead of scrolling sideways. */
|
|
190
|
+
.doc-title {
|
|
191
|
+
field-sizing: content;
|
|
192
|
+
text-wrap: balance;
|
|
193
|
+
}
|
|
194
|
+
</style>
|