@heyramzi/ui 2.9.0 → 2.10.1
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/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 +45 -3
- package/src/components/toolbar/toolbar-trigger.ts +8 -2
- package/src/record/demo-data.ts +4 -4
- package/src/record/record-demo.svelte +2 -2
- package/src/status/status-dot.svelte +0 -2
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
export const visibleIndexes = (slides)=>slides.flatMap((slide, index)=>slide.hidden ? [] : [
|
|
2
|
+
index
|
|
3
|
+
]);
|
|
4
|
+
const clamp = (value, min, max)=>Math.min(max, Math.max(min, value));
|
|
5
|
+
export function settle(slides, position) {
|
|
6
|
+
const visible = visibleIndexes(slides);
|
|
7
|
+
if (visible.length === 0) return {
|
|
8
|
+
index: 0,
|
|
9
|
+
step: 0
|
|
10
|
+
};
|
|
11
|
+
const index = visible.find((i)=>i >= position.index) ?? visible[visible.length - 1];
|
|
12
|
+
return {
|
|
13
|
+
index,
|
|
14
|
+
step: clamp(position.step, 0, slides[index].steps)
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
export function nextPosition(slides, from, loop = false) {
|
|
18
|
+
const visible = visibleIndexes(slides);
|
|
19
|
+
if (visible.length === 0) return null;
|
|
20
|
+
if (from.step < slides[from.index].steps) return {
|
|
21
|
+
index: from.index,
|
|
22
|
+
step: from.step + 1
|
|
23
|
+
};
|
|
24
|
+
const next = visible.find((i)=>i > from.index);
|
|
25
|
+
if (next !== undefined) return {
|
|
26
|
+
index: next,
|
|
27
|
+
step: 0
|
|
28
|
+
};
|
|
29
|
+
return loop ? {
|
|
30
|
+
index: visible[0],
|
|
31
|
+
step: 0
|
|
32
|
+
} : null;
|
|
33
|
+
}
|
|
34
|
+
export function prevPosition(slides, from, loop = false) {
|
|
35
|
+
const visible = visibleIndexes(slides);
|
|
36
|
+
if (visible.length === 0) return null;
|
|
37
|
+
if (from.step > 0) return {
|
|
38
|
+
index: from.index,
|
|
39
|
+
step: from.step - 1
|
|
40
|
+
};
|
|
41
|
+
const before = visible.filter((i)=>i < from.index);
|
|
42
|
+
const index = before.length ? before[before.length - 1] : loop ? visible[visible.length - 1] : undefined;
|
|
43
|
+
return index === undefined ? null : {
|
|
44
|
+
index,
|
|
45
|
+
step: slides[index].steps
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
export function ordinalOf(slides, index) {
|
|
49
|
+
const visible = visibleIndexes(slides);
|
|
50
|
+
return {
|
|
51
|
+
n: Math.max(0, visible.indexOf(index)) + 1,
|
|
52
|
+
of: visible.length
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
export function progressOf(slides, position) {
|
|
56
|
+
const visible = visibleIndexes(slides);
|
|
57
|
+
if (visible.length === 0) return 0;
|
|
58
|
+
const at = Math.max(0, visible.indexOf(position.index));
|
|
59
|
+
const steps = slides[position.index]?.steps ?? 0;
|
|
60
|
+
const share = steps > 0 ? (position.step + 1) / (steps + 1) : 1;
|
|
61
|
+
return (at + share) / visible.length;
|
|
62
|
+
}
|
|
63
|
+
export function parseSlideParam(raw, total) {
|
|
64
|
+
if (!raw || !/^\d+$/.test(raw)) return null;
|
|
65
|
+
const index = Number(raw) - 1;
|
|
66
|
+
return index >= 0 && index < total ? index : null;
|
|
67
|
+
}
|
|
68
|
+
const KEYS = {
|
|
69
|
+
ArrowRight: "next",
|
|
70
|
+
PageDown: "next",
|
|
71
|
+
ArrowLeft: "prev",
|
|
72
|
+
PageUp: "prev",
|
|
73
|
+
ArrowUp: "up",
|
|
74
|
+
ArrowDown: "down",
|
|
75
|
+
Home: "first",
|
|
76
|
+
End: "last",
|
|
77
|
+
Enter: "select",
|
|
78
|
+
Escape: "close",
|
|
79
|
+
o: "overview",
|
|
80
|
+
O: "overview",
|
|
81
|
+
f: "fullscreen",
|
|
82
|
+
F: "fullscreen",
|
|
83
|
+
p: "presenter",
|
|
84
|
+
P: "presenter"
|
|
85
|
+
};
|
|
86
|
+
export function keyAction(key, shift = false) {
|
|
87
|
+
if (key === " ") return shift ? "prev" : "next";
|
|
88
|
+
return KEYS[key] ?? null;
|
|
89
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export function defineStatuses(map) {
|
|
2
|
+
const lookup = map;
|
|
3
|
+
const find = (id)=>lookup[id];
|
|
4
|
+
return {
|
|
5
|
+
map,
|
|
6
|
+
ids: Object.keys(map),
|
|
7
|
+
has: (id)=>find(id) !== undefined,
|
|
8
|
+
get: find,
|
|
9
|
+
label: (id)=>find(id)?.label ?? id,
|
|
10
|
+
tone: (id)=>find(id)?.tone ?? "neutral",
|
|
11
|
+
icon: (id)=>find(id)?.icon,
|
|
12
|
+
variant: (id)=>find(id)?.variant ?? "open",
|
|
13
|
+
progress: (id)=>find(id)?.progress,
|
|
14
|
+
color: (id)=>find(id)?.color
|
|
15
|
+
};
|
|
16
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { default as StatusBadge } from "../../src/status/status-badge.svelte";
|
|
2
|
+
export { default as StatusDot } from "../../src/status/status-dot.svelte";
|
|
3
|
+
export { default as StatusIcon } from "../../src/status/status-icon.svelte";
|
|
4
|
+
export { defineStatuses } from "./define-statuses.js";
|
|
File without changes
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
class ObserverStub {
|
|
2
|
+
observe() {}
|
|
3
|
+
unobserve() {}
|
|
4
|
+
disconnect() {}
|
|
5
|
+
takeRecords() {
|
|
6
|
+
return [];
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
globalThis.ResizeObserver ??= ObserverStub;
|
|
10
|
+
globalThis.IntersectionObserver ??= ObserverStub;
|
|
11
|
+
globalThis.matchMedia ??= (query)=>({
|
|
12
|
+
matches: false,
|
|
13
|
+
media: query,
|
|
14
|
+
onchange: null,
|
|
15
|
+
addEventListener () {},
|
|
16
|
+
removeEventListener () {},
|
|
17
|
+
addListener () {},
|
|
18
|
+
removeListener () {},
|
|
19
|
+
dispatchEvent: ()=>false
|
|
20
|
+
});
|
|
21
|
+
if (globalThis.SVGElement && !("getTotalLength" in globalThis.SVGElement.prototype)) {
|
|
22
|
+
Object.defineProperty(globalThis.SVGElement.prototype, "getTotalLength", {
|
|
23
|
+
value: ()=>100,
|
|
24
|
+
configurable: true
|
|
25
|
+
});
|
|
26
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { DEFAULT_THREAD_LABELS } from "./types.js";
|
|
2
|
+
function at(iso) {
|
|
3
|
+
const ms = Date.parse(iso);
|
|
4
|
+
return Number.isNaN(ms) ? Number.POSITIVE_INFINITY : ms;
|
|
5
|
+
}
|
|
6
|
+
function time(comment) {
|
|
7
|
+
return at(comment.createdAt);
|
|
8
|
+
}
|
|
9
|
+
function byTime(comments) {
|
|
10
|
+
return comments.map((comment, index)=>({
|
|
11
|
+
comment,
|
|
12
|
+
index
|
|
13
|
+
})).toSorted((a, b)=>time(a.comment) - time(b.comment) || a.index - b.index).map((row)=>row.comment);
|
|
14
|
+
}
|
|
15
|
+
export function buildThread(comments) {
|
|
16
|
+
const byId = new Map(comments.map((comment)=>[
|
|
17
|
+
comment.id,
|
|
18
|
+
comment
|
|
19
|
+
]));
|
|
20
|
+
function rootOf(comment) {
|
|
21
|
+
const seen = new Set([
|
|
22
|
+
comment.id
|
|
23
|
+
]);
|
|
24
|
+
let current = comment;
|
|
25
|
+
for(;;){
|
|
26
|
+
const parent = current.parentId ? byId.get(current.parentId) : undefined;
|
|
27
|
+
if (!parent) return current;
|
|
28
|
+
if (seen.has(parent.id)) return comment;
|
|
29
|
+
seen.add(parent.id);
|
|
30
|
+
current = parent;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
const replies = new Map();
|
|
34
|
+
const roots = [];
|
|
35
|
+
for (const comment of comments){
|
|
36
|
+
const root = rootOf(comment);
|
|
37
|
+
if (root.id === comment.id) roots.push(comment);
|
|
38
|
+
else replies.set(root.id, [
|
|
39
|
+
...replies.get(root.id) ?? [],
|
|
40
|
+
comment
|
|
41
|
+
]);
|
|
42
|
+
}
|
|
43
|
+
return byTime(roots).map((comment)=>({
|
|
44
|
+
comment,
|
|
45
|
+
replies: byTime(replies.get(comment.id) ?? [])
|
|
46
|
+
}));
|
|
47
|
+
}
|
|
48
|
+
export function resolvedCount(nodes) {
|
|
49
|
+
return nodes.filter((node)=>node.comment.resolved).length;
|
|
50
|
+
}
|
|
51
|
+
export function resolveThreadLabels(overrides) {
|
|
52
|
+
return {
|
|
53
|
+
...DEFAULT_THREAD_LABELS,
|
|
54
|
+
...overrides
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
export function fillCount(label, count) {
|
|
58
|
+
return label.replaceAll("{count}", String(count));
|
|
59
|
+
}
|
|
60
|
+
export function interleave(nodes, events) {
|
|
61
|
+
const timed = [
|
|
62
|
+
...nodes.map((node, index)=>({
|
|
63
|
+
at: at(node.comment.createdAt),
|
|
64
|
+
index,
|
|
65
|
+
node
|
|
66
|
+
})),
|
|
67
|
+
...events.map((event, index)=>({
|
|
68
|
+
at: at(event.at),
|
|
69
|
+
index: nodes.length + index,
|
|
70
|
+
event
|
|
71
|
+
}))
|
|
72
|
+
].toSorted((a, b)=>a.at - b.at || a.index - b.index);
|
|
73
|
+
const items = [];
|
|
74
|
+
for (const row of timed){
|
|
75
|
+
if ("node" in row) {
|
|
76
|
+
items.push({
|
|
77
|
+
type: "node",
|
|
78
|
+
key: row.node.comment.id,
|
|
79
|
+
node: row.node
|
|
80
|
+
});
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
const last = items.at(-1);
|
|
84
|
+
if (last?.type === "events") last.events.push(row.event);
|
|
85
|
+
else items.push({
|
|
86
|
+
type: "events",
|
|
87
|
+
key: row.event.id,
|
|
88
|
+
events: [
|
|
89
|
+
row.event
|
|
90
|
+
]
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
return items;
|
|
94
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export const DEFAULT_THREAD_LABELS = {
|
|
2
|
+
title: "Activity",
|
|
3
|
+
empty: "No comments yet",
|
|
4
|
+
placeholder: "Leave a comment",
|
|
5
|
+
replyPlaceholder: "Reply",
|
|
6
|
+
send: "Comment",
|
|
7
|
+
sending: "Sending",
|
|
8
|
+
reply: "Reply",
|
|
9
|
+
edit: "Edit comment",
|
|
10
|
+
delete: "Delete comment",
|
|
11
|
+
edited: "edited",
|
|
12
|
+
save: "Save",
|
|
13
|
+
cancel: "Cancel",
|
|
14
|
+
resolve: "Resolve",
|
|
15
|
+
unresolve: "Reopen",
|
|
16
|
+
resolved: "Resolved",
|
|
17
|
+
showResolved: "Show {count} resolved",
|
|
18
|
+
hideResolved: "Hide resolved",
|
|
19
|
+
agent: "AI",
|
|
20
|
+
pinned: "Pinned",
|
|
21
|
+
showMore: "Show more",
|
|
22
|
+
showLess: "Show less"
|
|
23
|
+
};
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
const DIGITS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
|
2
|
+
const INT_DIGITS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
|
3
|
+
const ZERO = DIGITS.charAt(0);
|
|
4
|
+
function integerLength(head) {
|
|
5
|
+
const i = INT_DIGITS.indexOf(head);
|
|
6
|
+
if (i === -1) throw new Error("invalid order key head: " + head);
|
|
7
|
+
const half = INT_DIGITS.length / 2;
|
|
8
|
+
return i < half ? half - i + 1 : i - half + 2;
|
|
9
|
+
}
|
|
10
|
+
function integerPart(key) {
|
|
11
|
+
const length = integerLength(key.charAt(0));
|
|
12
|
+
if (length > key.length) throw new Error("invalid order key: " + key);
|
|
13
|
+
return key.slice(0, length);
|
|
14
|
+
}
|
|
15
|
+
function smallestInteger() {
|
|
16
|
+
return INT_DIGITS.charAt(0) + ZERO.repeat(INT_DIGITS.length / 2);
|
|
17
|
+
}
|
|
18
|
+
function midpoint(a, b) {
|
|
19
|
+
if (b != null && a >= b) throw new Error(a + " >= " + b);
|
|
20
|
+
if (a.slice(-1) === ZERO || b && b.slice(-1) === ZERO) throw new Error("trailing zero");
|
|
21
|
+
if (b) {
|
|
22
|
+
let n = 0;
|
|
23
|
+
while((a[n] ?? ZERO) === b[n])n++;
|
|
24
|
+
if (n > 0) return b.slice(0, n) + midpoint(a.slice(n), b.slice(n));
|
|
25
|
+
}
|
|
26
|
+
const digitA = a ? DIGITS.indexOf(a.charAt(0)) : 0;
|
|
27
|
+
const digitB = b != null ? DIGITS.indexOf(b.charAt(0)) : DIGITS.length;
|
|
28
|
+
if (digitB - digitA > 1) {
|
|
29
|
+
return DIGITS.charAt(Math.round(0.5 * (digitA + digitB)));
|
|
30
|
+
}
|
|
31
|
+
if (b && b.length > 1) return b.slice(0, 1);
|
|
32
|
+
return DIGITS.charAt(digitA) + midpoint(a.slice(1), null);
|
|
33
|
+
}
|
|
34
|
+
function incrementInteger(x) {
|
|
35
|
+
const head = x.charAt(0);
|
|
36
|
+
let trailing = "";
|
|
37
|
+
for(let i = x.length - 1; i >= 1; i--){
|
|
38
|
+
const d = DIGITS.indexOf(x.charAt(i)) + 1;
|
|
39
|
+
if (d === DIGITS.length) trailing = ZERO + trailing;
|
|
40
|
+
else return head + x.slice(1, i) + DIGITS.charAt(d) + trailing;
|
|
41
|
+
}
|
|
42
|
+
const headIndex = INT_DIGITS.indexOf(head);
|
|
43
|
+
if (headIndex === INT_DIGITS.length - 1) return null;
|
|
44
|
+
const h = INT_DIGITS.charAt(headIndex + 1);
|
|
45
|
+
const delta = integerLength(h) - integerLength(head);
|
|
46
|
+
return h + (delta > 0 ? trailing + ZERO : delta < 0 ? trailing.slice(1) : trailing);
|
|
47
|
+
}
|
|
48
|
+
function decrementInteger(x) {
|
|
49
|
+
const head = x.charAt(0);
|
|
50
|
+
const last = DIGITS.charAt(DIGITS.length - 1);
|
|
51
|
+
let trailing = "";
|
|
52
|
+
for(let i = x.length - 1; i >= 1; i--){
|
|
53
|
+
const d = DIGITS.indexOf(x.charAt(i)) - 1;
|
|
54
|
+
if (d === -1) trailing = last + trailing;
|
|
55
|
+
else return head + x.slice(1, i) + DIGITS.charAt(d) + trailing;
|
|
56
|
+
}
|
|
57
|
+
const headIndex = INT_DIGITS.indexOf(head);
|
|
58
|
+
if (headIndex === 0) return null;
|
|
59
|
+
const h = INT_DIGITS.charAt(headIndex - 1);
|
|
60
|
+
const delta = integerLength(h) - integerLength(head);
|
|
61
|
+
return h + (delta > 0 ? trailing + last : delta < 0 ? trailing.slice(1) : trailing);
|
|
62
|
+
}
|
|
63
|
+
export function keyBetween(a, b) {
|
|
64
|
+
if (a != null && b != null && a > b) [a, b] = [
|
|
65
|
+
b,
|
|
66
|
+
a
|
|
67
|
+
];
|
|
68
|
+
if (a == null) {
|
|
69
|
+
if (b == null) return INT_DIGITS.charAt(INT_DIGITS.length / 2) + ZERO;
|
|
70
|
+
const ib = integerPart(b);
|
|
71
|
+
const fb = b.slice(ib.length);
|
|
72
|
+
if (ib === smallestInteger()) return ib + midpoint("", fb);
|
|
73
|
+
if (ib < b) return ib;
|
|
74
|
+
const res = decrementInteger(ib);
|
|
75
|
+
if (res == null) throw new Error("cannot decrement any more");
|
|
76
|
+
return res;
|
|
77
|
+
}
|
|
78
|
+
if (b == null) {
|
|
79
|
+
const ia = integerPart(a);
|
|
80
|
+
const fa = a.slice(ia.length);
|
|
81
|
+
const i = incrementInteger(ia);
|
|
82
|
+
return i == null ? ia + midpoint(fa, null) : i;
|
|
83
|
+
}
|
|
84
|
+
const ia = integerPart(a);
|
|
85
|
+
const fa = a.slice(ia.length);
|
|
86
|
+
const ib = integerPart(b);
|
|
87
|
+
const fb = b.slice(ib.length);
|
|
88
|
+
if (ia === ib) return ia + midpoint(fa, fb);
|
|
89
|
+
const i = incrementInteger(ia);
|
|
90
|
+
if (i == null) throw new Error("cannot increment any more");
|
|
91
|
+
if (i < b) return i;
|
|
92
|
+
return ia + midpoint(fa, null);
|
|
93
|
+
}
|
|
94
|
+
export function boardOrderAt(column, index, order) {
|
|
95
|
+
let lower = null;
|
|
96
|
+
for (const item of column.slice(0, index)){
|
|
97
|
+
const key = order(item);
|
|
98
|
+
if (key != null && (lower === null || key > lower)) lower = key;
|
|
99
|
+
}
|
|
100
|
+
let upper = null;
|
|
101
|
+
for (const item of column.slice(index)){
|
|
102
|
+
const key = order(item);
|
|
103
|
+
if (key != null && (lower === null || key > lower)) {
|
|
104
|
+
upper = key;
|
|
105
|
+
break;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return keyBetween(lower, upper);
|
|
109
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
const DAY_MS = 86_400_000;
|
|
2
|
+
export function dayNumber(iso) {
|
|
3
|
+
const [y = 1970, m = 1, d = 1] = iso.slice(0, 10).split("-").map(Number);
|
|
4
|
+
return Math.round(Date.UTC(y, m - 1, d) / DAY_MS);
|
|
5
|
+
}
|
|
6
|
+
export function isoFromDay(day) {
|
|
7
|
+
return new Date(day * DAY_MS).toISOString().slice(0, 10);
|
|
8
|
+
}
|
|
9
|
+
export function addDays(iso, days) {
|
|
10
|
+
return isoFromDay(dayNumber(iso) + days);
|
|
11
|
+
}
|
|
12
|
+
export function todayIso() {
|
|
13
|
+
const now = new Date();
|
|
14
|
+
const local = new Date(now.getTime() - now.getTimezoneOffset() * 60_000);
|
|
15
|
+
return local.toISOString().slice(0, 10);
|
|
16
|
+
}
|
|
17
|
+
export function weekday(day) {
|
|
18
|
+
return new Date(day * DAY_MS).getUTCDay();
|
|
19
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export const DEFAULT_TASK_DETAIL_LABELS = {
|
|
2
|
+
markComplete: "Mark complete",
|
|
3
|
+
markIncomplete: "Mark incomplete",
|
|
4
|
+
editTitle: "Edit title",
|
|
5
|
+
description: "Description",
|
|
6
|
+
addDescription: "Add a description",
|
|
7
|
+
editDescription: "Edit description",
|
|
8
|
+
save: "Save",
|
|
9
|
+
saving: "Saving",
|
|
10
|
+
cancel: "Cancel",
|
|
11
|
+
comments: "Activity",
|
|
12
|
+
commentPlaceholder: "Leave a comment",
|
|
13
|
+
commentSend: "Comment",
|
|
14
|
+
commentEdit: "Edit comment",
|
|
15
|
+
commentDelete: "Delete comment",
|
|
16
|
+
commentEdited: "edited",
|
|
17
|
+
commentsEmpty: "No comments yet",
|
|
18
|
+
ai: "AI",
|
|
19
|
+
properties: "Properties"
|
|
20
|
+
};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export function parseStamp(value) {
|
|
2
|
+
if (value === null || value === undefined || value === "") return null;
|
|
3
|
+
const date = value instanceof Date ? value : new Date(value);
|
|
4
|
+
return Number.isNaN(date.getTime()) ? null : date;
|
|
5
|
+
}
|
|
6
|
+
function yearOf(date, { locale = "en-US", timeZone }) {
|
|
7
|
+
return new Intl.DateTimeFormat(locale, {
|
|
8
|
+
year: "numeric",
|
|
9
|
+
timeZone
|
|
10
|
+
}).format(date);
|
|
11
|
+
}
|
|
12
|
+
export function shortDate(value, options = {}) {
|
|
13
|
+
const date = parseStamp(value);
|
|
14
|
+
if (!date) return "";
|
|
15
|
+
const { locale = "en-US", timeZone, now = new Date() } = options;
|
|
16
|
+
const sameYear = yearOf(date, options) === yearOf(now, options);
|
|
17
|
+
return new Intl.DateTimeFormat(locale, {
|
|
18
|
+
month: "short",
|
|
19
|
+
day: "numeric",
|
|
20
|
+
year: sameYear ? undefined : "numeric",
|
|
21
|
+
timeZone
|
|
22
|
+
}).format(date);
|
|
23
|
+
}
|
|
24
|
+
export function editStamp(value, options = {}) {
|
|
25
|
+
const date = parseStamp(value);
|
|
26
|
+
if (!date) return "";
|
|
27
|
+
const { locale = "en-US", timeZone } = options;
|
|
28
|
+
const time = new Intl.DateTimeFormat(locale, {
|
|
29
|
+
hour: "2-digit",
|
|
30
|
+
minute: "2-digit",
|
|
31
|
+
hour12: false,
|
|
32
|
+
timeZone
|
|
33
|
+
}).format(date);
|
|
34
|
+
return `${shortDate(date, options)}, ${time}`;
|
|
35
|
+
}
|
|
36
|
+
export function editedLabel(value, label = "Edited", options = {}) {
|
|
37
|
+
const day = shortDate(value, options);
|
|
38
|
+
return day ? `${label} ${day}` : label;
|
|
39
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { default as DocEditorPage } from "../../../src/work/docs/doc-editor-page.svelte";
|
|
2
|
+
export { default as DocMenu } from "../../../src/work/docs/doc-menu.svelte";
|
|
3
|
+
export { default as EditedChip } from "../../../src/work/docs/edited-chip.svelte";
|
|
4
|
+
export { DEFAULT_DOC_LABELS, docLabels } from "./labels.js";
|
|
5
|
+
export { anchorIds, headingsOf, outlineOf, outlineOfDoc, slugify } from "./outline.js";
|
|
6
|
+
export { editStamp, editedLabel, parseStamp, shortDate } from "./edited.js";
|
|
7
|
+
export { copyOptions, filterMenu, menuItems, shortcutLabel, shortcutTarget } from "./menu.js";
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export const DEFAULT_DOC_LABELS = {
|
|
2
|
+
titlePlaceholder: "New document",
|
|
3
|
+
untitled: "Untitled",
|
|
4
|
+
edited: "Edited",
|
|
5
|
+
showAuthorNames: "Show author names",
|
|
6
|
+
ownedBy: "Owned by",
|
|
7
|
+
lastEditBy: "Last edit by",
|
|
8
|
+
showHistory: "Show document history",
|
|
9
|
+
menu: "Document actions",
|
|
10
|
+
filter: "Filter…",
|
|
11
|
+
noResults: "Nothing matches",
|
|
12
|
+
moveTo: "Move to",
|
|
13
|
+
duplicate: "Duplicate",
|
|
14
|
+
rename: "Rename",
|
|
15
|
+
template: "New template from document",
|
|
16
|
+
favorite: "Favorite",
|
|
17
|
+
unfavorite: "Remove from favorites",
|
|
18
|
+
copy: "Copy",
|
|
19
|
+
copyUrl: "Copy URL",
|
|
20
|
+
copyTitle: "Copy title",
|
|
21
|
+
copyTitleAsLink: "Copy title as link",
|
|
22
|
+
copyMarkdown: "Copy content as Markdown",
|
|
23
|
+
remind: "Remind me",
|
|
24
|
+
history: "Show document history",
|
|
25
|
+
delete: "Delete",
|
|
26
|
+
deleteTitle: (title)=>`Delete "${title}"`,
|
|
27
|
+
deleteDetail: "This can't be undone.",
|
|
28
|
+
cancel: "Cancel",
|
|
29
|
+
back: "Back",
|
|
30
|
+
outline: "Outline",
|
|
31
|
+
copyLink: "Copy link"
|
|
32
|
+
};
|
|
33
|
+
export function docLabels(partial) {
|
|
34
|
+
return {
|
|
35
|
+
...DEFAULT_DOC_LABELS,
|
|
36
|
+
...partial
|
|
37
|
+
};
|
|
38
|
+
}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { tiptapToMarkdown } from "../../editor/markdown.js";
|
|
2
|
+
export const SHORTCUTS = {
|
|
3
|
+
move: {
|
|
4
|
+
key: "P",
|
|
5
|
+
shift: true
|
|
6
|
+
},
|
|
7
|
+
rename: {
|
|
8
|
+
key: "R",
|
|
9
|
+
shift: true
|
|
10
|
+
},
|
|
11
|
+
favorite: {
|
|
12
|
+
key: "F",
|
|
13
|
+
alt: true
|
|
14
|
+
},
|
|
15
|
+
remind: {
|
|
16
|
+
key: "H",
|
|
17
|
+
shift: true
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
export function shortcutLabel(shortcut) {
|
|
21
|
+
return `${shortcut.shift ? "⇧" : ""}${shortcut.alt ? "⌥" : ""}${shortcut.key.toUpperCase()}`;
|
|
22
|
+
}
|
|
23
|
+
export function menuItems(available, labels, options = {}) {
|
|
24
|
+
const all = [
|
|
25
|
+
{
|
|
26
|
+
id: "move",
|
|
27
|
+
label: labels.moveTo,
|
|
28
|
+
group: 0
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
id: "duplicate",
|
|
32
|
+
label: labels.duplicate,
|
|
33
|
+
group: 0
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
id: "rename",
|
|
37
|
+
label: labels.rename,
|
|
38
|
+
group: 0
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
id: "template",
|
|
42
|
+
label: labels.template,
|
|
43
|
+
group: 0
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
id: "favorite",
|
|
47
|
+
label: options.favorited ? labels.unfavorite : labels.favorite,
|
|
48
|
+
group: 1
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
id: "copy",
|
|
52
|
+
label: labels.copy,
|
|
53
|
+
submenu: true,
|
|
54
|
+
group: 1
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
id: "remind",
|
|
58
|
+
label: labels.remind,
|
|
59
|
+
group: 1
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
id: "history",
|
|
63
|
+
label: labels.history,
|
|
64
|
+
group: 2
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
id: "delete",
|
|
68
|
+
label: labels.delete,
|
|
69
|
+
danger: true,
|
|
70
|
+
group: 2
|
|
71
|
+
}
|
|
72
|
+
];
|
|
73
|
+
return all.filter((item)=>available[item.id]).map((item)=>Object.assign(item, {
|
|
74
|
+
shortcut: SHORTCUTS[item.id]
|
|
75
|
+
}));
|
|
76
|
+
}
|
|
77
|
+
export function filterMenu(items, query) {
|
|
78
|
+
const words = query.toLowerCase().split(/\s+/).filter(Boolean);
|
|
79
|
+
if (words.length === 0) return items;
|
|
80
|
+
return items.filter((item)=>{
|
|
81
|
+
const label = item.label.toLowerCase();
|
|
82
|
+
return words.every((word)=>label.includes(word));
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
export function shortcutTarget(event, items) {
|
|
86
|
+
if (event.metaKey || event.ctrlKey) return null;
|
|
87
|
+
const hit = items.find((item)=>item.shortcut && event.code === `Key${item.shortcut.key.toUpperCase()}` && !!item.shortcut.shift === event.shiftKey && !!item.shortcut.alt === event.altKey);
|
|
88
|
+
return hit?.id ?? null;
|
|
89
|
+
}
|
|
90
|
+
export function copyOptions(source, labels) {
|
|
91
|
+
const title = source.title.trim() || labels.untitled;
|
|
92
|
+
const options = [];
|
|
93
|
+
if (source.url) options.push({
|
|
94
|
+
kind: "url",
|
|
95
|
+
label: labels.copyUrl,
|
|
96
|
+
text: source.url
|
|
97
|
+
});
|
|
98
|
+
options.push({
|
|
99
|
+
kind: "title",
|
|
100
|
+
label: labels.copyTitle,
|
|
101
|
+
text: title
|
|
102
|
+
});
|
|
103
|
+
if (source.url) {
|
|
104
|
+
options.push({
|
|
105
|
+
kind: "link",
|
|
106
|
+
label: labels.copyTitleAsLink,
|
|
107
|
+
text: `[${title.replace(/([[\]\\])/g, "\\$1")}](${source.url})`
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
if (source.content) {
|
|
111
|
+
options.push({
|
|
112
|
+
kind: "markdown",
|
|
113
|
+
label: labels.copyMarkdown,
|
|
114
|
+
text: tiptapToMarkdown(source.content)
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
return options;
|
|
118
|
+
}
|
|
119
|
+
export function deleteName(title, labels) {
|
|
120
|
+
return title.trim() || labels.untitled;
|
|
121
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { anchorIds } from "../../editor/anchors.js";
|
|
2
|
+
export { anchorIds, slugify } from "../../editor/anchors.js";
|
|
3
|
+
function textOf(node) {
|
|
4
|
+
if (node.type === "text") return node.text ?? "";
|
|
5
|
+
return (node.content ?? []).map(textOf).join("");
|
|
6
|
+
}
|
|
7
|
+
export function headingsOf(doc) {
|
|
8
|
+
const found = [];
|
|
9
|
+
const walk = (node)=>{
|
|
10
|
+
if (node.type === "heading") {
|
|
11
|
+
const level = typeof node.attrs?.level === "number" ? node.attrs.level : 1;
|
|
12
|
+
found.push({
|
|
13
|
+
label: textOf(node).trim(),
|
|
14
|
+
level
|
|
15
|
+
});
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
for (const child of node.content ?? [])walk(child);
|
|
19
|
+
};
|
|
20
|
+
if (doc && typeof doc === "object") walk(doc);
|
|
21
|
+
const ids = anchorIds(found.map((heading)=>heading.label));
|
|
22
|
+
return found.map((heading, i)=>({
|
|
23
|
+
id: ids[i],
|
|
24
|
+
label: heading.label,
|
|
25
|
+
level: heading.level
|
|
26
|
+
}));
|
|
27
|
+
}
|
|
28
|
+
export function outlineOf(headings) {
|
|
29
|
+
const items = headings.filter((heading)=>(heading.level === 2 || heading.level === 3) && heading.label !== "");
|
|
30
|
+
if (items.length < 2) return [];
|
|
31
|
+
return items.map(({ id, label, level })=>({
|
|
32
|
+
id,
|
|
33
|
+
label,
|
|
34
|
+
level
|
|
35
|
+
}));
|
|
36
|
+
}
|
|
37
|
+
export function outlineOfDoc(doc) {
|
|
38
|
+
return outlineOf(headingsOf(doc));
|
|
39
|
+
}
|