@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/modules.test.ts
CHANGED
|
@@ -1,41 +1,10 @@
|
|
|
1
1
|
import { existsSync, readFileSync } from "node:fs";
|
|
2
2
|
import { dirname, join } from "node:path";
|
|
3
3
|
import { fileURLToPath } from "node:url";
|
|
4
|
-
import { describe, expect, it
|
|
5
|
-
import * as status from "./status/index.js";
|
|
6
|
-
import * as panel from "./panel/index.js";
|
|
4
|
+
import { describe, expect, it } from "vite-plus/test";
|
|
7
5
|
import * as record from "./record/index.js";
|
|
8
6
|
import * as inbox from "./inbox/index.js";
|
|
9
7
|
import * as thread from "./thread/index.js";
|
|
10
|
-
import type {
|
|
11
|
-
PanelStat as FromTasksPanelStat,
|
|
12
|
-
SidePanelWidth as FromTasksWidth,
|
|
13
|
-
StatusDef as FromTasksStatusDef,
|
|
14
|
-
StatusDotVariant as FromTasksVariant,
|
|
15
|
-
StatusId as FromTasksId,
|
|
16
|
-
StatusMap as FromTasksMap,
|
|
17
|
-
Statuses as FromTasksStatuses,
|
|
18
|
-
} from "./tasks/index.js";
|
|
19
|
-
import type { PanelStat, SidePanelWidth } from "./panel/index.js";
|
|
20
|
-
import type {
|
|
21
|
-
StatusDef,
|
|
22
|
-
StatusDotVariant,
|
|
23
|
-
StatusId,
|
|
24
|
-
StatusMap,
|
|
25
|
-
Statuses,
|
|
26
|
-
} from "./status/index.js";
|
|
27
|
-
|
|
28
|
-
// Both spellings of every moved type have to be the same type.
|
|
29
|
-
type Same<A, B> = [A] extends [B] ? ([B] extends [A] ? true : false) : false;
|
|
30
|
-
const sameTypes: [
|
|
31
|
-
Same<PanelStat, FromTasksPanelStat>,
|
|
32
|
-
Same<SidePanelWidth, FromTasksWidth>,
|
|
33
|
-
Same<StatusDef, FromTasksStatusDef>,
|
|
34
|
-
Same<StatusDotVariant, FromTasksVariant>,
|
|
35
|
-
Same<StatusId<{ a: StatusDef }>, FromTasksId<{ a: StatusDef }>>,
|
|
36
|
-
Same<StatusMap, FromTasksMap>,
|
|
37
|
-
Same<Statuses, FromTasksStatuses>,
|
|
38
|
-
] = [true, true, true, true, true, true, true];
|
|
39
8
|
|
|
40
9
|
const pkg = JSON.parse(
|
|
41
10
|
readFileSync(join(dirname(fileURLToPath(import.meta.url)), "..", "package.json"), "utf8"),
|
|
@@ -44,23 +13,6 @@ const pkg = JSON.parse(
|
|
|
44
13
|
};
|
|
45
14
|
|
|
46
15
|
describe("module split", () => {
|
|
47
|
-
it("keeps every moved name on tasks, the same object as on its new module", async () => {
|
|
48
|
-
// The kanban board reads matchMedia on import, and jsdom has none.
|
|
49
|
-
vi.stubGlobal("matchMedia", () => ({
|
|
50
|
-
matches: false,
|
|
51
|
-
addEventListener() {},
|
|
52
|
-
removeEventListener() {},
|
|
53
|
-
}));
|
|
54
|
-
const tasks = await import("./tasks/index.js");
|
|
55
|
-
expect(sameTypes).toHaveLength(7);
|
|
56
|
-
expect(tasks.StatusBadge).toBe(status.StatusBadge);
|
|
57
|
-
expect(tasks.StatusDot).toBe(status.StatusDot);
|
|
58
|
-
expect(tasks.StatusIcon).toBe(status.StatusIcon);
|
|
59
|
-
expect(tasks.defineStatuses).toBe(status.defineStatuses);
|
|
60
|
-
expect(tasks.StatusBadge).toBeDefined();
|
|
61
|
-
expect(tasks.SidePanel).toBe(panel.SidePanel);
|
|
62
|
-
});
|
|
63
|
-
|
|
64
16
|
it("holds the record page's names", () => {
|
|
65
17
|
expect(record.RecordShell).toBeDefined();
|
|
66
18
|
expect(record.DEFAULT_RECORD_LABELS).toBeDefined();
|
|
@@ -84,22 +36,10 @@ describe("module split", () => {
|
|
|
84
36
|
expect(missing).toEqual([]);
|
|
85
37
|
});
|
|
86
38
|
|
|
87
|
-
it("
|
|
88
|
-
for (const name of [
|
|
89
|
-
"./tasks",
|
|
90
|
-
"./tasks/status",
|
|
91
|
-
"./tasks/status-dot",
|
|
92
|
-
"./tasks/statuses",
|
|
93
|
-
"./tasks/side-panel",
|
|
94
|
-
"./tasks/record",
|
|
95
|
-
"./tasks/inbox",
|
|
96
|
-
"./status",
|
|
97
|
-
"./panel",
|
|
98
|
-
"./record",
|
|
99
|
-
"./thread",
|
|
100
|
-
"./inbox",
|
|
101
|
-
]) {
|
|
39
|
+
it("exports each module once, under its own name", () => {
|
|
40
|
+
for (const name of ["./work", "./status", "./panel", "./record", "./thread", "./inbox"]) {
|
|
102
41
|
expect(pkg.exports[name], name).toBeDefined();
|
|
103
42
|
}
|
|
43
|
+
expect(Object.keys(pkg.exports).filter((name) => name.startsWith("./tasks"))).toEqual([]);
|
|
104
44
|
});
|
|
105
45
|
});
|
package/src/panel/README.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# @heyramzi/ui/panel
|
|
2
2
|
|
|
3
|
-
`SidePanel`, a sheet for one record: badges, links out to other tools, a copy-a-prompt handoff and a stats strip. `PanelStat` types one stat. It used to live in `@heyramzi/ui/
|
|
3
|
+
`SidePanel`, a sheet for one record: badges, links out to other tools, a copy-a-prompt handoff and a stats strip. `PanelStat` types one stat. It used to live in `@heyramzi/ui/work`, which still re-exports both, and `tasks/side-panel` still resolves.
|
|
4
4
|
|
|
5
5
|
Exports: `SidePanel` and the types `PanelStat`, `SidePanelWidth`.
|
package/src/record/README.md
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
# @heyramzi/ui/record
|
|
2
2
|
|
|
3
|
-
The page shell for a project or a client record: header, where-we-are, next up, stats, steps rail, timeline, project list and field sections.
|
|
3
|
+
The page shell for a project or a client record: header, where-we-are, next up, stats, steps rail, timeline, project list and field sections.
|
package/src/record/demo-data.ts
CHANGED
|
@@ -185,7 +185,7 @@ export const websiteEvents: RecordEvent[] = [
|
|
|
185
185
|
{ label: "Length", value: "45 min" },
|
|
186
186
|
{ label: "With", value: "Jane Roe, Tom Bell" },
|
|
187
187
|
],
|
|
188
|
-
href: "#
|
|
188
|
+
href: "#",
|
|
189
189
|
},
|
|
190
190
|
{
|
|
191
191
|
id: "w3",
|
|
@@ -233,7 +233,7 @@ export const websiteEvents: RecordEvent[] = [
|
|
|
233
233
|
export const website: RecordSummary = {
|
|
234
234
|
id: "p-web",
|
|
235
235
|
name: "Website rebuild",
|
|
236
|
-
href: "#
|
|
236
|
+
href: "#",
|
|
237
237
|
stageKey: "sent",
|
|
238
238
|
value: 12000,
|
|
239
239
|
currency: "EUR",
|
|
@@ -254,7 +254,7 @@ export const website: RecordSummary = {
|
|
|
254
254
|
export const audit: RecordSummary = {
|
|
255
255
|
id: "p-audit",
|
|
256
256
|
name: "Brand audit",
|
|
257
|
-
href: "#
|
|
257
|
+
href: "#",
|
|
258
258
|
stageKey: "lost",
|
|
259
259
|
stageDetail: "Price",
|
|
260
260
|
value: 4500,
|
|
@@ -272,7 +272,7 @@ export const audit: RecordSummary = {
|
|
|
272
272
|
export const portal: RecordSummary = {
|
|
273
273
|
id: "p-portal",
|
|
274
274
|
name: "Booking portal",
|
|
275
|
-
href: "#
|
|
275
|
+
href: "#",
|
|
276
276
|
stageKey: "paid",
|
|
277
277
|
value: 18000,
|
|
278
278
|
paid: 18000,
|
|
@@ -166,7 +166,7 @@
|
|
|
166
166
|
{#snippet display(row: InfoRow, clamp = false)}
|
|
167
167
|
{#if row.chips?.length}
|
|
168
168
|
<span class="flex flex-wrap items-center gap-1">
|
|
169
|
-
{#each row.chips as chip (
|
|
169
|
+
{#each row.chips as chip, i (i)}
|
|
170
170
|
<StatusBadge tone={chip.tone ?? "neutral"} capitalize={false}>{chip.label}</StatusBadge>
|
|
171
171
|
{/each}
|
|
172
172
|
</span>
|
|
@@ -175,6 +175,7 @@
|
|
|
175
175
|
{:else if row.href && row.value}
|
|
176
176
|
<a
|
|
177
177
|
href={row.href}
|
|
178
|
+
title={row.value}
|
|
178
179
|
class={cn(
|
|
179
180
|
"min-w-0 truncate text-sm font-medium underline-offset-2 hover:underline",
|
|
180
181
|
clamp &&
|
|
@@ -262,7 +263,7 @@
|
|
|
262
263
|
<dt
|
|
263
264
|
class={cn(
|
|
264
265
|
"flex items-center gap-1.5 text-xs text-muted-foreground",
|
|
265
|
-
labelPosition === "beside"
|
|
266
|
+
labelPosition === "beside" ? "shrink-0" : "[overflow-wrap:anywhere]",
|
|
266
267
|
)}
|
|
267
268
|
>
|
|
268
269
|
{#if row.term}
|
|
@@ -301,7 +302,7 @@
|
|
|
301
302
|
<h2 class="text-xs font-medium tracking-wide text-muted-foreground uppercase">{title}</h2>
|
|
302
303
|
{/if}
|
|
303
304
|
<dl
|
|
304
|
-
class="grid grid-cols-[minmax(5rem,max-content)_minmax(0,1fr)] items-start gap-x-4 gap-y-2.5"
|
|
305
|
+
class="grid grid-cols-[minmax(5rem,min(max-content,45%))_minmax(0,1fr)] items-start gap-x-4 gap-y-2.5"
|
|
305
306
|
>
|
|
306
307
|
{#each shown as row, index (row.divider ? `divider-${index}` : keyOf(row))}
|
|
307
308
|
{#if row.divider}
|
|
@@ -311,7 +312,7 @@
|
|
|
311
312
|
{@const long = row.input === "longtext"}
|
|
312
313
|
<dt
|
|
313
314
|
class={cn(
|
|
314
|
-
"flex min-h-7 items-center gap-2 text-sm text-muted-foreground",
|
|
315
|
+
"flex min-h-7 min-w-0 items-center gap-2 text-sm [overflow-wrap:anywhere] text-muted-foreground",
|
|
315
316
|
long && "col-span-2 min-h-0",
|
|
316
317
|
)}
|
|
317
318
|
>
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
import StatusBadge from "../status/status-badge.svelte";
|
|
9
9
|
import { gutterClass } from "./gutter.js";
|
|
10
10
|
import { formatRange } from "./format.js";
|
|
11
|
-
import { todayIso } from "../
|
|
11
|
+
import { todayIso } from "../work/dates.js";
|
|
12
12
|
import { resolveLabels, type RecordLabels, type RecordNext } from "./types.js";
|
|
13
13
|
|
|
14
14
|
// =========================
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
import { Progress } from "../shadcn/progress/index.js";
|
|
7
7
|
import { TONE_TEXT } from "../lib/tone.js";
|
|
8
8
|
import StatusBadge from "../status/status-badge.svelte";
|
|
9
|
-
import { todayIso } from "../
|
|
9
|
+
import { todayIso } from "../work/dates.js";
|
|
10
10
|
import { formatMoney, formatRange } from "./format.js";
|
|
11
11
|
import {
|
|
12
12
|
resolveLabels,
|
|
@@ -198,7 +198,7 @@
|
|
|
198
198
|
{#snippet header()}
|
|
199
199
|
<RecordHeader
|
|
200
200
|
title={website.name}
|
|
201
|
-
parent={{ label: "Marlow & Finch", href: "#
|
|
201
|
+
parent={{ label: "Marlow & Finch", href: "#" }}
|
|
202
202
|
stage={stage ? { label: stage.label, tone: stage.tone } : null}
|
|
203
203
|
facts={[
|
|
204
204
|
formatMoney(website.value ?? 0, "EUR", locale),
|
|
@@ -287,7 +287,7 @@
|
|
|
287
287
|
{#snippet header()}
|
|
288
288
|
<RecordHeader
|
|
289
289
|
title="Marlow & Finch"
|
|
290
|
-
parent={{ label: "Clients", href: "#
|
|
290
|
+
parent={{ label: "Clients", href: "#" }}
|
|
291
291
|
facts={[
|
|
292
292
|
`Pipeline ${formatMoney(rollup.totals.EUR?.pipeline ?? 0, "EUR", locale, true)}`,
|
|
293
293
|
`Won ${formatMoney(rollup.totals.EUR?.won ?? 0, "EUR", locale, true)}`,
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
import { Skeleton } from "../shadcn/skeleton/index.js";
|
|
19
19
|
import * as Popover from "../shadcn/popover/index.js";
|
|
20
20
|
import * as ContextMenu from "../shadcn/context-menu/index.js";
|
|
21
|
-
import { todayIso } from "../
|
|
21
|
+
import { todayIso } from "../work/dates.js";
|
|
22
22
|
import { formatRange } from "./format.js";
|
|
23
23
|
import {
|
|
24
24
|
groupSteps,
|
|
@@ -280,8 +280,8 @@
|
|
|
280
280
|
<DotsThreeVertical class="size-4" weight="bold" />
|
|
281
281
|
{#if hiddenCount > 0}
|
|
282
282
|
<span
|
|
283
|
-
class="absolute -top-0.5 -right-0.5 flex
|
|
284
|
-
>{hiddenCount}</span
|
|
283
|
+
class="absolute -top-0.5 -right-0.5 flex h-4 min-w-4 items-center justify-center rounded-full bg-muted px-1 text-xs font-medium tabular-nums"
|
|
284
|
+
>{hiddenCount.toLocaleString()}</span
|
|
285
285
|
>
|
|
286
286
|
{/if}
|
|
287
287
|
</Button>
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { type VariantProps, tv } from "tailwind-variants";
|
|
3
3
|
|
|
4
4
|
export const badgeVariants = tv({
|
|
5
|
-
base: "h-5 gap-1 rounded-full border border-transparent px-2 py-0.5 text-xs font-medium has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&>svg]:size-3! focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive group/badge inline-flex w-fit shrink-0 items-center justify-center overflow-hidden whitespace-nowrap transition-[background-color,border-color,color,box-shadow] focus-visible:ring-[3px] [&>svg]:pointer-events-none",
|
|
5
|
+
base: "h-5 gap-1 rounded-full border border-transparent px-2 py-0.5 text-xs font-medium has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&>svg]:size-3! focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive group/badge inline-flex w-fit max-w-full shrink-0 items-center justify-center overflow-hidden whitespace-nowrap transition-[background-color,border-color,color,box-shadow] focus-visible:ring-[3px] [&>svg]:pointer-events-none",
|
|
6
6
|
variants: {
|
|
7
7
|
// Three weights a label can carry: filled, tinted, outlined. Severity is the
|
|
8
8
|
// `tone` prop, which reads `TONE_CLASS`, not a variant.
|
|
@@ -2,11 +2,7 @@
|
|
|
2
2
|
import type { HTMLAttributes } from "svelte/elements";
|
|
3
3
|
import { cn, type WithElementRef } from "../../lib/utils.js";
|
|
4
4
|
|
|
5
|
-
// WHY: card titles
|
|
6
|
-
|
|
7
|
-
// but a page whose sections are all cards ends up with no headings below the h1, so screen readers cannot navigate it by heading (WCAG 2.4.6).
|
|
8
|
-
|
|
9
|
-
// Pass `as="h2"` on real section titles.
|
|
5
|
+
// WHY: card titles default to a div, so pass `as="h2"` on real section titles or a page of cards has no headings for screen readers (WCAG 2.4.6).
|
|
10
6
|
let {
|
|
11
7
|
ref = $bindable(null),
|
|
12
8
|
class: className,
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
bind:this={ref}
|
|
15
15
|
data-slot="empty-description"
|
|
16
16
|
class={cn(
|
|
17
|
-
"text-sm/relaxed text-muted-foreground [&>a:hover]:text-primary text-sm/relaxed [&>a]:underline [&>a]:underline-offset-4",
|
|
17
|
+
"text-sm/relaxed text-muted-foreground [overflow-wrap:anywhere] [&>a:hover]:text-primary text-sm/relaxed [&>a]:underline [&>a]:underline-offset-4",
|
|
18
18
|
className,
|
|
19
19
|
)}
|
|
20
20
|
{...restProps}
|
|
@@ -15,6 +15,13 @@
|
|
|
15
15
|
/** The fill's colour on the severity scale. Left out, the primary colour. */
|
|
16
16
|
tone?: Tone;
|
|
17
17
|
} = $props();
|
|
18
|
+
|
|
19
|
+
// WHY clamped: a value past max drew a positive translateX and the fill left its track.
|
|
20
|
+
let pct = $derived.by(() => {
|
|
21
|
+
const top = max && max > 0 ? max : 1;
|
|
22
|
+
const raw = (100 * (value ?? 0)) / top;
|
|
23
|
+
return Number.isFinite(raw) ? Math.min(100, Math.max(0, raw)) : 0;
|
|
24
|
+
});
|
|
18
25
|
</script>
|
|
19
26
|
|
|
20
27
|
<ProgressPrimitive.Root
|
|
@@ -31,6 +38,6 @@
|
|
|
31
38
|
<div
|
|
32
39
|
data-slot="progress-indicator"
|
|
33
40
|
class="{progressToneClass(tone)} size-full flex-1 transition-transform duration-[var(--duration-slow)] ease-[var(--ease-smooth-out)] motion-reduce:transition-none"
|
|
34
|
-
style="transform: translateX(-{100 -
|
|
41
|
+
style="transform: translateX(-{100 - pct}%)"
|
|
35
42
|
></div>
|
|
36
43
|
</ProgressPrimitive.Root>
|
|
@@ -5,15 +5,23 @@
|
|
|
5
5
|
let {
|
|
6
6
|
ref = $bindable(null),
|
|
7
7
|
class: className,
|
|
8
|
+
wrap = false,
|
|
8
9
|
children,
|
|
9
10
|
...restProps
|
|
10
|
-
}: WithElementRef<HTMLTdAttributes>
|
|
11
|
+
}: WithElementRef<HTMLTdAttributes> & {
|
|
12
|
+
/** Lets a long user string wrap, so a trailing action cell keeps its place. Off by default: amounts and dates stay on one line. */
|
|
13
|
+
wrap?: boolean;
|
|
14
|
+
} = $props();
|
|
11
15
|
</script>
|
|
12
16
|
|
|
13
17
|
<td
|
|
14
18
|
bind:this={ref}
|
|
15
19
|
data-slot="table-cell"
|
|
16
|
-
class={cn(
|
|
20
|
+
class={cn(
|
|
21
|
+
"p-2 align-middle tabular-nums [&:has([role=checkbox])]:pr-0",
|
|
22
|
+
wrap ? "whitespace-normal [overflow-wrap:anywhere]" : "whitespace-nowrap",
|
|
23
|
+
className,
|
|
24
|
+
)}
|
|
17
25
|
{...restProps}
|
|
18
26
|
>
|
|
19
27
|
{@render children?.()}
|
package/src/status/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @heyramzi/ui/status
|
|
2
2
|
|
|
3
|
-
Status badge, dot and icon from one map. `defineStatuses` builds the map, and the three parts read it, so a status looks the same everywhere. They used to live in `@heyramzi/ui/
|
|
3
|
+
Status badge, dot and icon from one map. `defineStatuses` builds the map, and the three parts read it, so a status looks the same everywhere. They used to live in `@heyramzi/ui/work`, which still re-exports every name.
|
|
4
4
|
|
|
5
5
|
```svelte
|
|
6
6
|
<script lang="ts">
|
package/src/thread/README.md
CHANGED
|
@@ -24,6 +24,8 @@ One comment thread for any subject: a task, a project, a doc or a diagram. The t
|
|
|
24
24
|
- **Resolve.** Pass `onResolve` and each root gets a check. Resolved roots fold away behind a "Show N resolved" button.
|
|
25
25
|
- **Anchor.** `anchor` carries `{ nodeId, dx, dy, x, y }` for a canvas pin. A pinned comment shows a chip, and `onAnchor` fires on a click so the canvas can move to the node. `anchorChip` replaces the chip.
|
|
26
26
|
- **Attachments.** The `attachments` snippet draws under a comment's body.
|
|
27
|
+
- **Events.** `events` takes `ThreadEvent`s (a whole sentence, a time, an optional Phosphor icon) and draws each as one `Trace` line between the conversations, in time order. `whenEvent(event)` formats its time. `interleave(nodes, events)` gives the same order without the component.
|
|
28
|
+
- **Long bodies.** A body over 6 lines folds behind `showMore` and `showLess`.
|
|
27
29
|
- **Labels.** Every string comes from `labels`, a partial of `ThreadLabels`. `showResolved` holds a `{count}` slot. `when(comment)` formats the time.
|
|
28
30
|
|
|
29
31
|
```ts
|
package/src/thread/index.ts
CHANGED
|
@@ -1,11 +1,19 @@
|
|
|
1
1
|
export { default as Thread } from "./thread.svelte";
|
|
2
|
-
export {
|
|
2
|
+
export {
|
|
3
|
+
buildThread,
|
|
4
|
+
fillCount,
|
|
5
|
+
interleave,
|
|
6
|
+
resolveThreadLabels,
|
|
7
|
+
resolvedCount,
|
|
8
|
+
} from "./logic.js";
|
|
3
9
|
export { DEFAULT_THREAD_LABELS } from "./types.js";
|
|
4
10
|
export type {
|
|
5
11
|
ThreadAnchor,
|
|
6
12
|
ThreadAuthor,
|
|
7
13
|
ThreadAuthorKind,
|
|
8
14
|
ThreadComment,
|
|
15
|
+
ThreadEvent,
|
|
16
|
+
ThreadItem,
|
|
9
17
|
ThreadLabels,
|
|
10
18
|
ThreadNode,
|
|
11
19
|
ThreadPost,
|
package/src/thread/logic.ts
CHANGED
|
@@ -1,11 +1,22 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {
|
|
2
|
+
ThreadComment,
|
|
3
|
+
ThreadEvent,
|
|
4
|
+
ThreadItem,
|
|
5
|
+
ThreadLabels,
|
|
6
|
+
ThreadNode,
|
|
7
|
+
} from "./types.js";
|
|
2
8
|
import { DEFAULT_THREAD_LABELS } from "./types.js";
|
|
3
9
|
|
|
4
|
-
|
|
5
|
-
|
|
10
|
+
/** A timestamp as a number, a malformed one last. */
|
|
11
|
+
function at(iso: string): number {
|
|
12
|
+
const ms = Date.parse(iso);
|
|
6
13
|
return Number.isNaN(ms) ? Number.POSITIVE_INFINITY : ms;
|
|
7
14
|
}
|
|
8
15
|
|
|
16
|
+
function time(comment: ThreadComment): number {
|
|
17
|
+
return at(comment.createdAt);
|
|
18
|
+
}
|
|
19
|
+
|
|
9
20
|
/** Oldest first, a malformed timestamp last, ties in the order they came. */
|
|
10
21
|
function byTime(comments: ThreadComment[]): ThreadComment[] {
|
|
11
22
|
return comments
|
|
@@ -59,3 +70,22 @@ export function resolveThreadLabels(overrides?: Partial<ThreadLabels>): ThreadLa
|
|
|
59
70
|
export function fillCount(label: string, count: number): string {
|
|
60
71
|
return label.replaceAll("{count}", String(count));
|
|
61
72
|
}
|
|
73
|
+
|
|
74
|
+
/** Conversations and events in time order, each run of events between two conversations as one item. */
|
|
75
|
+
export function interleave(nodes: ThreadNode[], events: ThreadEvent[]): ThreadItem[] {
|
|
76
|
+
const timed = [
|
|
77
|
+
...nodes.map((node, index) => ({ at: at(node.comment.createdAt), index, node })),
|
|
78
|
+
...events.map((event, index) => ({ at: at(event.at), index: nodes.length + index, event })),
|
|
79
|
+
].toSorted((a, b) => a.at - b.at || a.index - b.index);
|
|
80
|
+
const items: ThreadItem[] = [];
|
|
81
|
+
for (const row of timed) {
|
|
82
|
+
if ("node" in row) {
|
|
83
|
+
items.push({ type: "node", key: row.node.comment.id, node: row.node });
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
const last = items.at(-1);
|
|
87
|
+
if (last?.type === "events") last.events.push(row.event);
|
|
88
|
+
else items.push({ type: "events", key: row.event.id, events: [row.event] });
|
|
89
|
+
}
|
|
90
|
+
return items;
|
|
91
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { cn } from "../lib/utils.js";
|
|
3
|
+
|
|
4
|
+
interface Props {
|
|
5
|
+
text: string;
|
|
6
|
+
more: string;
|
|
7
|
+
less: string;
|
|
8
|
+
class?: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
let { text, more, less, class: className }: Props = $props();
|
|
12
|
+
|
|
13
|
+
let open = $state(false);
|
|
14
|
+
let long = $derived(text.length > 420 || text.split("\n").length > 6);
|
|
15
|
+
</script>
|
|
16
|
+
|
|
17
|
+
<div class="flex flex-col items-start gap-1">
|
|
18
|
+
<p
|
|
19
|
+
class={cn(
|
|
20
|
+
"text-sm leading-relaxed font-normal whitespace-pre-wrap text-pretty",
|
|
21
|
+
long && !open && "line-clamp-6",
|
|
22
|
+
className,
|
|
23
|
+
)}
|
|
24
|
+
>
|
|
25
|
+
{text}
|
|
26
|
+
</p>
|
|
27
|
+
{#if long}
|
|
28
|
+
<button
|
|
29
|
+
type="button"
|
|
30
|
+
class="text-muted-foreground hover:text-foreground text-xs underline-offset-2 hover:underline"
|
|
31
|
+
aria-expanded={open}
|
|
32
|
+
onclick={() => (open = !open)}
|
|
33
|
+
>
|
|
34
|
+
{open ? less : more}
|
|
35
|
+
</button>
|
|
36
|
+
{/if}
|
|
37
|
+
</div>
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import * as TraceUI from "../shadcn/trace/index.js";
|
|
3
|
+
import type { ThreadEvent } from "./types.js";
|
|
4
|
+
|
|
5
|
+
interface Props {
|
|
6
|
+
events: ThreadEvent[];
|
|
7
|
+
when: (event: ThreadEvent) => string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
let { events, when }: Props = $props();
|
|
11
|
+
</script>
|
|
12
|
+
|
|
13
|
+
<!-- ps-1 centres each 16px icon in the 24px avatar column the comments use. -->
|
|
14
|
+
<TraceUI.Trace class="gap-1 ps-1">
|
|
15
|
+
{#each events as event (event.id)}
|
|
16
|
+
{@const Icon = event.icon}
|
|
17
|
+
<TraceUI.Line class="w-full items-start text-xs">
|
|
18
|
+
{#if Icon}
|
|
19
|
+
<TraceUI.Icon class="mt-px"><Icon size={14} /></TraceUI.Icon>
|
|
20
|
+
{/if}
|
|
21
|
+
<!-- Wraps, not truncates: a status name can be a sentence, and a touch screen has no hover title. -->
|
|
22
|
+
<TraceUI.Title class="flex-1 whitespace-normal text-pretty [overflow-wrap:anywhere]"
|
|
23
|
+
>{event.title}</TraceUI.Title
|
|
24
|
+
>
|
|
25
|
+
<TraceUI.Description>
|
|
26
|
+
<time datetime={event.at}>{when(event)}</time>
|
|
27
|
+
</TraceUI.Description>
|
|
28
|
+
</TraceUI.Line>
|
|
29
|
+
{/each}
|
|
30
|
+
</TraceUI.Trace>
|