@heyramzi/ui 2.9.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.
Files changed (312) hide show
  1. package/dist/agents/helpers.js +52 -0
  2. package/dist/agents/index.js +3 -0
  3. package/dist/agents/page-state.js +65 -0
  4. package/dist/agents/types.js +1 -0
  5. package/dist/agents/vendor/color.js +149 -0
  6. package/dist/agents/vendor/draw.js +548 -0
  7. package/dist/agents/vendor/engine.js +632 -0
  8. package/dist/agents/vendor/mesh.js +727 -0
  9. package/dist/agents/vendor/plastic.js +3273 -0
  10. package/dist/agents/vendor/presets.js +171 -0
  11. package/dist/agents/vendor/shapes.js +24 -0
  12. package/dist/agents/vendor/ticker.js +56 -0
  13. package/dist/agents/vendor/types.js +0 -0
  14. package/dist/agents/vendor/wear.js +1525 -0
  15. package/dist/ai/ai-button/index.js +2 -0
  16. package/dist/ai/confirmation/confirmation-context.svelte.js +12 -0
  17. package/dist/ai/confirmation/index.js +9 -0
  18. package/dist/ai/generation-progress/index.js +2 -0
  19. package/dist/ai/index.js +11 -0
  20. package/dist/ai/loading-state/index.js +3 -0
  21. package/dist/ai/prompt-input/index.js +6 -0
  22. package/dist/ai/reasoning/index.js +4 -0
  23. package/dist/ai/reasoning/reasoning-context.svelte.js +12 -0
  24. package/dist/ai/response/index.js +3 -0
  25. package/dist/ai/suggestion/index.js +3 -0
  26. package/dist/ai/thinking-dots/index.js +3 -0
  27. package/dist/ai/typing-dots/index.js +2 -0
  28. package/dist/ai/voice-waveform/index.js +3 -0
  29. package/dist/animations/text-swap.js +30 -0
  30. package/dist/brand/index.js +65 -0
  31. package/dist/canvas/card/resize.js +10 -0
  32. package/dist/canvas/edges/edge-path.js +284 -0
  33. package/dist/canvas/editor/context-menu.js +42 -0
  34. package/dist/canvas/editor/dispatch.svelte.js +157 -0
  35. package/dist/canvas/editor/editor-context.js +8 -0
  36. package/dist/canvas/editor/editor-mode.js +0 -0
  37. package/dist/canvas/editor/frame.js +87 -0
  38. package/dist/canvas/editor/hand-context.js +8 -0
  39. package/dist/canvas/editor/history-core.js +221 -0
  40. package/dist/canvas/editor/keymap.js +193 -0
  41. package/dist/canvas/editor/layout-actions.js +170 -0
  42. package/dist/canvas/editor/lock.js +65 -0
  43. package/dist/canvas/editor/rebase.js +279 -0
  44. package/dist/canvas/editor/style.js +174 -0
  45. package/dist/canvas/editor/text-field-context.js +8 -0
  46. package/dist/canvas/editor/z-order.js +82 -0
  47. package/dist/canvas/headless/alignment.js +20 -0
  48. package/dist/canvas/headless/break-apart-find.js +324 -0
  49. package/dist/canvas/headless/break-apart-pieces.js +74 -0
  50. package/dist/canvas/headless/break-apart-plan.js +378 -0
  51. package/dist/canvas/headless/break-apart-style.js +93 -0
  52. package/dist/canvas/headless/break-apart.js +206 -0
  53. package/dist/canvas/headless/canvas-cleanup.js +70 -0
  54. package/dist/canvas/headless/edge-anchors.js +134 -0
  55. package/dist/canvas/headless/edge-memo.js +28 -0
  56. package/dist/canvas/headless/edge-serialization.js +31 -0
  57. package/dist/canvas/headless/figure-geometry.js +331 -0
  58. package/dist/canvas/headless/fit-viewport.js +82 -0
  59. package/dist/canvas/headless/grid.js +96 -0
  60. package/dist/canvas/headless/icon-node.js +45 -0
  61. package/dist/canvas/headless/index.js +1 -0
  62. package/dist/canvas/headless/linkify.js +25 -0
  63. package/dist/canvas/headless/pen-marks.js +115 -0
  64. package/dist/canvas/headless/sketch.js +250 -0
  65. package/dist/canvas/headless/snap-guides.js +100 -0
  66. package/dist/canvas/headless/svg-figure.js +137 -0
  67. package/dist/canvas/headless/table-layout.js +161 -0
  68. package/dist/canvas/index.js +25 -0
  69. package/dist/canvas/lod/lod-mode.svelte.js +22 -0
  70. package/dist/canvas/lod/render-all.svelte.js +45 -0
  71. package/dist/canvas/ops/arrange.js +83 -0
  72. package/dist/canvas/ops/ops.js +318 -0
  73. package/dist/canvas/pen/colors.js +41 -0
  74. package/dist/canvas/pen/eraser.js +35 -0
  75. package/dist/canvas/pen/geometry.js +143 -0
  76. package/dist/canvas/pen/index.js +9 -0
  77. package/dist/canvas/pen/ops.js +15 -0
  78. package/dist/canvas/pen/pen-session.js +171 -0
  79. package/dist/canvas/pen/plugin.js +129 -0
  80. package/dist/canvas/pen/shapes.js +80 -0
  81. package/dist/canvas/pen/stroke-path.js +37 -0
  82. package/dist/canvas/pen/types.js +30 -0
  83. package/dist/canvas/pen/ui.js +20 -0
  84. package/dist/canvas/plugin.js +51 -0
  85. package/dist/canvas/screen/glyphs.js +24 -0
  86. package/dist/canvas/screen/labels.js +24 -0
  87. package/dist/canvas/screen/parts.js +140 -0
  88. package/dist/canvas/screen/plugin.js +71 -0
  89. package/dist/canvas/screen/types.js +44 -0
  90. package/dist/canvas/screen/ui.js +13 -0
  91. package/dist/canvas/test-utils.js +18 -0
  92. package/dist/canvas/types.js +0 -0
  93. package/dist/canvas/ui/forward-wheel.js +27 -0
  94. package/dist/canvas/ui/icons.js +133 -0
  95. package/dist/canvas/ui/place-panel.js +57 -0
  96. package/dist/canvas/ui/shortcut-tip.js +18 -0
  97. package/dist/canvas/ui/tools.js +411 -0
  98. package/dist/charts/dashboard/chart.js +1 -0
  99. package/dist/charts/dashboard/data-table.js +7 -0
  100. package/dist/charts/dashboard/index.js +13 -0
  101. package/dist/charts/dashboard/windows.js +5 -0
  102. package/dist/charts/edge-fade.js +7 -0
  103. package/dist/charts/hover-band.js +13 -0
  104. package/dist/charts/index.js +19 -0
  105. package/dist/charts/motion.js +15 -0
  106. package/dist/charts/primitives/chart-utils.js +22 -0
  107. package/dist/charts/primitives/index.js +4 -0
  108. package/dist/components/copy/clipboard.js +38 -0
  109. package/dist/components/copy/copied.svelte.js +26 -0
  110. package/dist/components/copy/index.js +3 -0
  111. package/dist/components/data-table/data-table.js +55 -0
  112. package/dist/components/data-table/index.js +7 -0
  113. package/dist/components/docs/index.js +3 -0
  114. package/dist/components/docs/scroll-spy.svelte.js +71 -0
  115. package/dist/components/field-row/index.js +1 -0
  116. package/dist/components/hold-to-confirm/index.js +1 -0
  117. package/dist/components/icon/index.js +1 -0
  118. package/dist/components/language-flag/index.js +1 -0
  119. package/dist/components/list-page/filter-section.js +4 -0
  120. package/dist/components/list-page/index.js +25 -0
  121. package/dist/components/list-page/list-table.js +5 -0
  122. package/dist/components/list-page/queue-rail.js +3 -0
  123. package/dist/components/list-page/section-host.js +8 -0
  124. package/dist/components/list-page/step.js +5 -0
  125. package/dist/components/list-page/types.js +0 -0
  126. package/dist/components/locale-switch/index.js +1 -0
  127. package/dist/components/mark/index.js +1 -0
  128. package/dist/components/open-in/index.js +1 -0
  129. package/dist/components/picker/index.js +3 -0
  130. package/dist/components/picker/trigger.js +33 -0
  131. package/dist/components/picker/types.js +0 -0
  132. package/dist/components/section-card/index.js +1 -0
  133. package/dist/components/section-header/index.js +2 -0
  134. package/dist/components/segmented/collapse.js +32 -0
  135. package/dist/components/segmented/index.js +8 -0
  136. package/dist/components/segmented/segmented.js +50 -0
  137. package/dist/components/star-rating-input/index.js +2 -0
  138. package/dist/components/svg/index.js +1 -0
  139. package/dist/components/table-view/index.js +1 -0
  140. package/dist/components/table-view/types.js +0 -0
  141. package/dist/components/tags-input/index.js +2 -0
  142. package/dist/components/tags-input/tags.js +90 -0
  143. package/dist/components/theme/index.js +3 -0
  144. package/dist/components/toolbar/index.js +3 -0
  145. package/dist/components/toolbar/toolbar-trigger.js +4 -0
  146. package/dist/editor/anchors.js +17 -0
  147. package/dist/editor/block-id.js +62 -0
  148. package/dist/editor/block-ops.js +105 -0
  149. package/dist/editor/doc-blocks.js +181 -0
  150. package/dist/editor/extensions.js +200 -0
  151. package/dist/editor/index.js +4 -0
  152. package/dist/editor/markdown-test-helpers.js +6 -0
  153. package/dist/editor/markdown.js +486 -0
  154. package/dist/editor/serializer.js +268 -0
  155. package/dist/editor/slash-items.js +104 -0
  156. package/dist/editor/youtube-url.js +27 -0
  157. package/dist/effects/animated-beam/index.js +1 -0
  158. package/dist/effects/animated-beam/path-calculator.svelte.js +42 -0
  159. package/dist/effects/animated-beam/types.js +0 -0
  160. package/dist/effects/border-beam/css.js +420 -0
  161. package/dist/effects/border-beam/presets.js +1792 -0
  162. package/dist/effects/border-beam/register-properties.js +39 -0
  163. package/dist/effects/border-beam/types.js +0 -0
  164. package/dist/effects/image-comparison/compare.js +4 -0
  165. package/dist/effects/image-reveal/index.js +1 -0
  166. package/dist/effects/image-reveal/types.js +0 -0
  167. package/dist/effects/magnetic/magnetic.js +54 -0
  168. package/dist/effects/reveal/index.js +4 -0
  169. package/dist/effects/reveal/observe.js +43 -0
  170. package/dist/effects/reveal/types.js +0 -0
  171. package/dist/effects/shader-gradient/color.js +34 -0
  172. package/dist/effects/shader-gradient/index.js +1 -0
  173. package/dist/effects/shader-gradient/renderer.js +320 -0
  174. package/dist/effects/shader-gradient/shaders.js +280 -0
  175. package/dist/effects/shader-gradient/types.js +0 -0
  176. package/dist/icons/apple-symbol-exports.js +126 -0
  177. package/dist/icons/sf-symbols.js +465 -0
  178. package/dist/icons/trades.js +34 -0
  179. package/dist/inbox/index.js +4 -0
  180. package/dist/inbox/logic.js +156 -0
  181. package/dist/inbox/types.js +46 -0
  182. package/dist/index.js +18 -0
  183. package/dist/lib/arrive.js +13 -0
  184. package/dist/lib/icon-types.js +0 -0
  185. package/dist/lib/initials.js +17 -0
  186. package/dist/lib/layout.js +1 -0
  187. package/dist/lib/panel.js +3 -0
  188. package/dist/lib/result.js +26 -0
  189. package/dist/lib/sliding-pill.js +45 -0
  190. package/dist/lib/theme-transition.js +53 -0
  191. package/dist/lib/tone.js +32 -0
  192. package/dist/lib/utils.js +5 -0
  193. package/dist/onboarding/define-tours.js +28 -0
  194. package/dist/onboarding/index.js +4 -0
  195. package/dist/onboarding/onboarding.svelte.js +15 -0
  196. package/dist/onboarding/pick.js +16 -0
  197. package/dist/onboarding/stores.js +50 -0
  198. package/dist/onboarding/types.js +1 -0
  199. package/dist/onboarding/wait.js +25 -0
  200. package/dist/panel/index.js +1 -0
  201. package/dist/panel/side-panel-types.js +0 -0
  202. package/dist/record/demo-data.js +512 -0
  203. package/dist/record/fields.js +148 -0
  204. package/dist/record/format.js +97 -0
  205. package/dist/record/gutter.js +1 -0
  206. package/dist/record/index.js +15 -0
  207. package/dist/record/kinds.js +110 -0
  208. package/dist/record/logic.js +255 -0
  209. package/dist/record/types.js +52 -0
  210. package/dist/shadcn/accordion/index.js +5 -0
  211. package/dist/shadcn/alert/index.js +5 -0
  212. package/dist/shadcn/alert-dialog/index.js +12 -0
  213. package/dist/shadcn/attachment/index.js +10 -0
  214. package/dist/shadcn/avatar/index.js +7 -0
  215. package/dist/shadcn/badge/index.js +2 -0
  216. package/dist/shadcn/breadcrumb/index.js +8 -0
  217. package/dist/shadcn/bubble/index.js +5 -0
  218. package/dist/shadcn/button/index.js +2 -0
  219. package/dist/shadcn/calendar/index.js +19 -0
  220. package/dist/shadcn/card/index.js +8 -0
  221. package/dist/shadcn/checkbox/index.js +2 -0
  222. package/dist/shadcn/code-block/index.js +9 -0
  223. package/dist/shadcn/collapsible/index.js +4 -0
  224. package/dist/shadcn/command/index.js +13 -0
  225. package/dist/shadcn/context-menu/index.js +17 -0
  226. package/dist/shadcn/dialog/index.js +11 -0
  227. package/dist/shadcn/dropdown-menu/index.js +19 -0
  228. package/dist/shadcn/dropdown-menu/menu-item.js +23 -0
  229. package/dist/shadcn/empty/index.js +7 -0
  230. package/dist/shadcn/field/index.js +12 -0
  231. package/dist/shadcn/hooks/highlighter.js +92 -0
  232. package/dist/shadcn/hooks/is-mobile.svelte.js +7 -0
  233. package/dist/shadcn/hooks/use-highlighted-code.svelte.js +65 -0
  234. package/dist/shadcn/hover-card/index.js +5 -0
  235. package/dist/shadcn/input/index.js +3 -0
  236. package/dist/shadcn/input-otp/index.js +5 -0
  237. package/dist/shadcn/kbd/index.js +3 -0
  238. package/dist/shadcn/label/index.js +2 -0
  239. package/dist/shadcn/marker/index.js +4 -0
  240. package/dist/shadcn/message/index.js +7 -0
  241. package/dist/shadcn/message-scroller/index.js +8 -0
  242. package/dist/shadcn/popover/index.js +9 -0
  243. package/dist/shadcn/progress/index.js +2 -0
  244. package/dist/shadcn/progress/tone.js +11 -0
  245. package/dist/shadcn/radio-group/index.js +3 -0
  246. package/dist/shadcn/scroll-area/index.js +3 -0
  247. package/dist/shadcn/select/index.js +12 -0
  248. package/dist/shadcn/separator/index.js +2 -0
  249. package/dist/shadcn/sheet/index.js +11 -0
  250. package/dist/shadcn/sidebar/constants.js +6 -0
  251. package/dist/shadcn/sidebar/context.svelte.js +38 -0
  252. package/dist/shadcn/sidebar/index.js +25 -0
  253. package/dist/shadcn/skeleton/index.js +2 -0
  254. package/dist/shadcn/slider/index.js +2 -0
  255. package/dist/shadcn/sonner/index.js +1 -0
  256. package/dist/shadcn/spinner/index.js +1 -0
  257. package/dist/shadcn/switch/index.js +2 -0
  258. package/dist/shadcn/table/index.js +9 -0
  259. package/dist/shadcn/tabs/index.js +5 -0
  260. package/dist/shadcn/textarea/index.js +2 -0
  261. package/dist/shadcn/toggle/index.js +3 -0
  262. package/dist/shadcn/toggle-group/index.js +3 -0
  263. package/dist/shadcn/tooltip/context.js +8 -0
  264. package/dist/shadcn/tooltip/index.js +6 -0
  265. package/dist/shadcn/trace/index.js +9 -0
  266. package/dist/slides/bridges.js +66 -0
  267. package/dist/slides/deck-controller.svelte.js +221 -0
  268. package/dist/slides/export/capture.js +81 -0
  269. package/dist/slides/export/ffmpeg.js +85 -0
  270. package/dist/slides/export/index.js +4 -0
  271. package/dist/slides/export/launch.js +8 -0
  272. package/dist/slides/export/pdf.js +78 -0
  273. package/dist/slides/export/types.js +0 -0
  274. package/dist/slides/index.js +7 -0
  275. package/dist/slides/labels.js +26 -0
  276. package/dist/slides/layout.js +47 -0
  277. package/dist/slides/model.js +9 -0
  278. package/dist/slides/navigation.js +89 -0
  279. package/dist/slides/types.js +6 -0
  280. package/dist/status/define-statuses.js +16 -0
  281. package/dist/status/index.js +4 -0
  282. package/dist/status/status-types.js +0 -0
  283. package/dist/test-setup.js +26 -0
  284. package/dist/thread/index.js +3 -0
  285. package/dist/thread/logic.js +94 -0
  286. package/dist/thread/types.js +23 -0
  287. package/dist/work/board-order.js +109 -0
  288. package/dist/work/dates.js +19 -0
  289. package/dist/work/detail/detail-types.js +20 -0
  290. package/dist/work/docs/edited.js +39 -0
  291. package/dist/work/docs/index.js +7 -0
  292. package/dist/work/docs/labels.js +38 -0
  293. package/dist/work/docs/menu.js +121 -0
  294. package/dist/work/docs/outline.js +39 -0
  295. package/dist/work/gantt/logic.js +260 -0
  296. package/dist/work/inbox/inbox-logic.js +94 -0
  297. package/dist/work/inbox/inbox-statuses.js +86 -0
  298. package/dist/work/inbox/inbox-types.js +0 -0
  299. package/dist/work/inbox/index.js +1 -0
  300. package/dist/work/index.js +21 -0
  301. package/dist/work/kanban-drag.js +25 -0
  302. package/dist/work/kanban-types.js +0 -0
  303. package/dist/work/presets/sales.js +35 -0
  304. package/dist/work/reorder.js +10 -0
  305. package/dist/work/task-types.js +0 -0
  306. package/dist/work/time/duration.js +60 -0
  307. package/dist/work/time/time-types.js +25 -0
  308. package/dist/work/use-kanban-dnd.svelte.js +128 -0
  309. package/package.json +45 -3
  310. package/src/components/toolbar/toolbar-trigger.ts +8 -2
  311. package/src/record/demo-data.ts +4 -4
  312. package/src/record/record-demo.svelte +2 -2
@@ -0,0 +1,260 @@
1
+ import { dayNumber, isoFromDay, weekday } from "../dates.js";
2
+ const DAY_MS = 86_400_000;
3
+ export function dayX(layout, day) {
4
+ return (day - layout.first) * layout.dayWidth;
5
+ }
6
+ export function spanOf(item, { getStart, getEnd }) {
7
+ const first = getStart(item) || getEnd(item);
8
+ const last = getEnd(item) || getStart(item);
9
+ if (!first || !last) return null;
10
+ const start = dayNumber(first);
11
+ return {
12
+ start,
13
+ end: Math.max(start, dayNumber(last))
14
+ };
15
+ }
16
+ export function liveSpan(span, drag, id) {
17
+ if (!span || drag?.id !== id || drag.dx === 0) return span;
18
+ if (drag.mode === "move") return {
19
+ start: span.start + drag.dx,
20
+ end: span.end + drag.dx
21
+ };
22
+ if (drag.mode === "start") return {
23
+ start: Math.min(span.start + drag.dx, span.end),
24
+ end: span.end
25
+ };
26
+ return {
27
+ start: span.start,
28
+ end: Math.max(span.end + drag.dx, span.start)
29
+ };
30
+ }
31
+ function join(a, b) {
32
+ return !a ? b : !b ? a : {
33
+ start: Math.min(a.start, b.start),
34
+ end: Math.max(a.end, b.end)
35
+ };
36
+ }
37
+ export function rangeOf(items, source, todayDay, from, to) {
38
+ let lo = todayDay;
39
+ let hi = todayDay;
40
+ for (const item of items){
41
+ const span = spanOf(item, source);
42
+ if (!span) continue;
43
+ lo = Math.min(lo, span.start);
44
+ hi = Math.max(hi, span.end);
45
+ }
46
+ let first = from ? dayNumber(from) : lo - 7;
47
+ if (!from) first -= (weekday(first) + 6) % 7;
48
+ const last = to ? dayNumber(to) : hi + 21;
49
+ return {
50
+ first,
51
+ last: Math.max(last, first)
52
+ };
53
+ }
54
+ export function buildDays(first, count) {
55
+ return Array.from({
56
+ length: count
57
+ }, (_, i)=>{
58
+ const day = first + i;
59
+ const wd = weekday(day);
60
+ return {
61
+ day,
62
+ i,
63
+ date: Number(isoFromDay(day).slice(8, 10)),
64
+ wd,
65
+ weekend: wd === 0 || wd === 6
66
+ };
67
+ });
68
+ }
69
+ export function buildMonths(days, format) {
70
+ const out = [];
71
+ for (const d of days){
72
+ const key = isoFromDay(d.day).slice(0, 7);
73
+ const last = out.at(-1);
74
+ if (last?.key === key) last.length++;
75
+ else out.push({
76
+ key,
77
+ label: format.format(new Date(d.day * DAY_MS)),
78
+ i: d.i,
79
+ length: 1
80
+ });
81
+ }
82
+ return out;
83
+ }
84
+ export function buildRows(items, source) {
85
+ const { getId, getParent, groups, getGroup, folded, drag } = source;
86
+ const out = [];
87
+ let order = 0;
88
+ const live = (item, id)=>liveSpan(spanOf(item, source), drag, id);
89
+ const emit = (members)=>{
90
+ if (!getParent) {
91
+ for (const item of members){
92
+ const id = getId(item);
93
+ const own = live(item, id);
94
+ out.push({
95
+ kind: "task",
96
+ item,
97
+ id,
98
+ order: order++,
99
+ depth: 0,
100
+ hasChildren: false,
101
+ open: true,
102
+ own,
103
+ span: own
104
+ });
105
+ }
106
+ return;
107
+ }
108
+ const ids = new Set(members.map((item)=>getId(item)));
109
+ const kids = new Map();
110
+ for (const item of members){
111
+ const parent = getParent(item);
112
+ const key = parent && ids.has(parent) ? parent : null;
113
+ kids.set(key, [
114
+ ...kids.get(key) ?? [],
115
+ item
116
+ ]);
117
+ }
118
+ const walk = (item, depth, visible)=>{
119
+ const id = getId(item);
120
+ const children = kids.get(id) ?? [];
121
+ const open = !folded.has(id);
122
+ const own = live(item, id);
123
+ const row = {
124
+ kind: "task",
125
+ item,
126
+ id,
127
+ order: 0,
128
+ depth,
129
+ hasChildren: children.length > 0,
130
+ open,
131
+ own,
132
+ span: own
133
+ };
134
+ if (visible) {
135
+ row.order = order++;
136
+ out.push(row);
137
+ }
138
+ let below = null;
139
+ for (const child of children)below = join(below, walk(child, depth + 1, visible && open));
140
+ if (!own) row.span = below;
141
+ return join(own, below);
142
+ };
143
+ for (const item of kids.get(null) ?? [])walk(item, 0, true);
144
+ };
145
+ if (!groups || !getGroup) {
146
+ emit(items);
147
+ return out;
148
+ }
149
+ for (const group of groups){
150
+ const members = items.filter((item)=>getGroup(item) === group.id);
151
+ let span = null;
152
+ for (const item of members)span = join(span, live(item, getId(item)));
153
+ out.push({
154
+ kind: "group",
155
+ group,
156
+ count: members.length,
157
+ span
158
+ });
159
+ emit(members);
160
+ }
161
+ return out;
162
+ }
163
+ export function roundedPath(points, radius) {
164
+ let d = `M${points[0][0]},${points[0][1]}`;
165
+ for(let i = 1; i < points.length - 1; i++){
166
+ const [px, py] = points[i - 1];
167
+ const [cx, cy] = points[i];
168
+ const [nx, ny] = points[i + 1];
169
+ const r = Math.min(radius, Math.hypot(cx - px, cy - py) / 2, Math.hypot(nx - cx, ny - cy) / 2);
170
+ const inX = cx - Math.sign(cx - px) * r;
171
+ const inY = cy - Math.sign(cy - py) * r;
172
+ const outX = cx + Math.sign(nx - cx) * r;
173
+ const outY = cy + Math.sign(ny - cy) * r;
174
+ d += ` L${inX},${inY} Q${cx},${cy} ${outX},${outY}`;
175
+ }
176
+ const [lx, ly] = points[points.length - 1];
177
+ return `${d} L${lx},${ly}`;
178
+ }
179
+ export function buildArrows(rows, layout, getDependsOn) {
180
+ const { rowHeight, inset } = layout;
181
+ const at = new Map();
182
+ rows.forEach((row, index)=>{
183
+ if (row.kind === "task" && row.span) at.set(row.id, {
184
+ row: index,
185
+ span: row.span
186
+ });
187
+ });
188
+ const out = [];
189
+ for (const row of rows){
190
+ if (row.kind !== "task") continue;
191
+ const target = at.get(row.id);
192
+ if (!target) continue;
193
+ for (const dep of getDependsOn(row.item) ?? []){
194
+ const source = at.get(dep);
195
+ if (!source) continue;
196
+ const x1 = dayX(layout, source.span.end + 1) - inset;
197
+ const y1 = source.row * rowHeight + rowHeight / 2;
198
+ const x2 = dayX(layout, target.span.start) + inset;
199
+ const y2 = target.row * rowHeight + rowHeight / 2;
200
+ const points = x2 - x1 >= 24 ? [
201
+ [
202
+ x1,
203
+ y1
204
+ ],
205
+ [
206
+ x1 + 12,
207
+ y1
208
+ ],
209
+ [
210
+ x1 + 12,
211
+ y2
212
+ ],
213
+ [
214
+ x2,
215
+ y2
216
+ ]
217
+ ] : [
218
+ [
219
+ x1,
220
+ y1
221
+ ],
222
+ [
223
+ x1 + 10,
224
+ y1
225
+ ],
226
+ [
227
+ x1 + 10,
228
+ y1 + (y2 > y1 ? rowHeight / 2 : -rowHeight / 2)
229
+ ],
230
+ [
231
+ x2 - 12,
232
+ y1 + (y2 > y1 ? rowHeight / 2 : -rowHeight / 2)
233
+ ],
234
+ [
235
+ x2 - 12,
236
+ y2
237
+ ],
238
+ [
239
+ x2,
240
+ y2
241
+ ]
242
+ ];
243
+ out.push({
244
+ key: `${dep}->${row.id}`,
245
+ d: roundedPath(points, 6),
246
+ head: `M${x2 - 5},${y2 - 3.5} L${x2},${y2} L${x2 - 5},${y2 + 3.5}`,
247
+ from: dep,
248
+ to: row.id
249
+ });
250
+ }
251
+ }
252
+ return out;
253
+ }
254
+ export function barWidth(span, layout) {
255
+ return Math.max((span.end - span.start + 1) * layout.dayWidth - layout.inset * 2, 8);
256
+ }
257
+ export function rangeLabel(span, format) {
258
+ const length = span.end - span.start + 1;
259
+ return `${format.format(new Date(span.start * DAY_MS))} to ${format.format(new Date(span.end * DAY_MS))}, ${length} ${length === 1 ? "day" : "days"}`;
260
+ }
@@ -0,0 +1,94 @@
1
+ export function startDraft(drafts, recommended) {
2
+ return drafts.find((draft)=>draft.templateId === recommended) ?? drafts[0];
3
+ }
4
+ export function isOpen(item) {
5
+ return item.tier === "ask" && item.state === "proposed";
6
+ }
7
+ export function canUndo(item) {
8
+ return item.tier === "auto" && item.state === "done";
9
+ }
10
+ function plain(text) {
11
+ return text.replace(/(…|\.{3})\s*$/, "").replace(/\s+/g, " ").trim().toLowerCase();
12
+ }
13
+ export function cardFacts(item) {
14
+ const { command, summary, detail } = item.proposal;
15
+ const shown = [
16
+ plain(item.title)
17
+ ];
18
+ if (command) shown.push(plain(`${command.tool}: ${command.text}`), plain(command.text));
19
+ const lines = [];
20
+ for (const raw of [
21
+ summary,
22
+ detail
23
+ ]){
24
+ let line = raw?.trim() ?? "";
25
+ const title = item.title.trim();
26
+ if (line.toLowerCase().startsWith(title.toLowerCase()) && line.length > title.length) {
27
+ line = line.slice(title.length).replace(/^[\s:.,;-]+/, "");
28
+ }
29
+ const key = plain(line);
30
+ if (!key || shown.some((seen)=>seen.includes(key) || key.includes(seen))) continue;
31
+ shown.push(key);
32
+ lines.push(line);
33
+ }
34
+ return {
35
+ lines,
36
+ command
37
+ };
38
+ }
39
+ export function freshReasoning(item, facts) {
40
+ const reasoning = item.trace.reasoning.trim();
41
+ const key = plain(reasoning);
42
+ if (!key) return "";
43
+ const said = [
44
+ item.title,
45
+ item.proposal.summary,
46
+ item.proposal.detail ?? "",
47
+ ...facts.lines
48
+ ].map(plain).filter(Boolean);
49
+ return said.some((line)=>line.includes(key) || key.includes(line)) ? "" : reasoning;
50
+ }
51
+ const ISO = /^\d{4}-\d{2}-\d{2}T/;
52
+ const UNITS = [
53
+ [
54
+ 604_800,
55
+ "week"
56
+ ],
57
+ [
58
+ 86_400,
59
+ "day"
60
+ ],
61
+ [
62
+ 3_600,
63
+ "hour"
64
+ ],
65
+ [
66
+ 60,
67
+ "minute"
68
+ ]
69
+ ];
70
+ export function whenOf(at, now = Date.now(), locale = "en-GB") {
71
+ if (!ISO.test(at)) return at;
72
+ const time = Date.parse(at);
73
+ if (Number.isNaN(time)) return "";
74
+ const seconds = Math.round((time - now) / 1000);
75
+ const age = Math.abs(seconds);
76
+ if (age >= 4 * 604_800) {
77
+ return new Intl.DateTimeFormat(locale, {
78
+ month: "short",
79
+ day: "numeric"
80
+ }).format(time);
81
+ }
82
+ const rtf = new Intl.RelativeTimeFormat(locale, {
83
+ numeric: "auto",
84
+ style: "short"
85
+ });
86
+ for (const [size, unit] of UNITS){
87
+ if (age >= size) return rtf.format(Math.round(seconds / size), unit);
88
+ }
89
+ return rtf.format(0, "second");
90
+ }
91
+ export function isTyping(target) {
92
+ if (!(target instanceof HTMLElement)) return false;
93
+ return target.isContentEditable || /^(INPUT|TEXTAREA|SELECT)$/.test(target.tagName);
94
+ }
@@ -0,0 +1,86 @@
1
+ import { defineStatuses } from "../../status/define-statuses.js";
2
+ import { ClipboardText, EnvelopeSimple, Hash, Phone } from "phosphor-svelte";
3
+ export const inboxStates = defineStatuses({
4
+ proposed: {
5
+ label: "Needs you",
6
+ tone: "warning",
7
+ variant: "open"
8
+ },
9
+ working: {
10
+ label: "Agent working",
11
+ tone: "accent",
12
+ variant: "progress",
13
+ progress: 0.6
14
+ },
15
+ approved: {
16
+ label: "Approved",
17
+ tone: "success",
18
+ variant: "completed"
19
+ },
20
+ declined: {
21
+ label: "Declined",
22
+ tone: "neutral",
23
+ variant: "lost"
24
+ },
25
+ done: {
26
+ label: "Done by agent",
27
+ tone: "success",
28
+ variant: "completed"
29
+ },
30
+ undone: {
31
+ label: "Undone",
32
+ tone: "neutral",
33
+ variant: "lost"
34
+ }
35
+ });
36
+ export const inboxKinds = defineStatuses({
37
+ information: {
38
+ label: "Information",
39
+ tone: "info",
40
+ variant: "filled"
41
+ },
42
+ action: {
43
+ label: "Action",
44
+ tone: "accent",
45
+ variant: "filled"
46
+ },
47
+ decision: {
48
+ label: "Decision",
49
+ tone: "warning",
50
+ variant: "filled"
51
+ }
52
+ });
53
+ export const inboxConfidence = defineStatuses({
54
+ high: {
55
+ label: "Confident",
56
+ tone: "success",
57
+ variant: "progress"
58
+ },
59
+ medium: {
60
+ label: "Unsure",
61
+ tone: "warning",
62
+ variant: "progress"
63
+ },
64
+ low: {
65
+ label: "Guessing",
66
+ tone: "destructive",
67
+ variant: "progress"
68
+ }
69
+ });
70
+ export function confidenceLevel(score) {
71
+ if (score >= 0.8) return "high";
72
+ if (score >= 0.5) return "medium";
73
+ return "low";
74
+ }
75
+ export const SOURCE_ICON = {
76
+ call: Phone,
77
+ email: EnvelopeSimple,
78
+ slack: Hash,
79
+ form: ClipboardText
80
+ };
81
+ export const SOURCE_LABEL = {
82
+ call: "Call",
83
+ email: "Email",
84
+ slack: "Slack",
85
+ form: "Form"
86
+ };
File without changes
@@ -0,0 +1 @@
1
+ export { confidenceLevel, inboxConfidence, inboxKinds, inboxStates } from "./inbox-statuses.js";
@@ -0,0 +1,21 @@
1
+ export { default as KanbanBoard } from "../../src/work/kanban-board.svelte";
2
+ export { default as KanbanColumn } from "../../src/work/kanban-column.svelte";
3
+ export { liftDragImage } from "./kanban-drag.js";
4
+ export { createKanbanDnd } from "./use-kanban-dnd.svelte.js";
5
+ export { boardOrderAt, keyBetween } from "./board-order.js";
6
+ export { reorderByIds } from "./reorder.js";
7
+ export { default as TaskList } from "../../src/work/task-list.svelte";
8
+ export { default as TaskGantt } from "../../src/work/task-gantt.svelte";
9
+ export { addDays, dayNumber, isoFromDay, todayIso } from "./dates.js";
10
+ export { default as TaskDetail } from "../../src/work/detail/task-detail.svelte";
11
+ export { default as TaskThread } from "../../src/work/detail/task-thread.svelte";
12
+ export { default as TaskProperty } from "../../src/work/detail/task-property.svelte";
13
+ export { default as TaskChip } from "../../src/work/detail/task-chip.svelte";
14
+ export { DEFAULT_TASK_DETAIL_LABELS } from "./detail/detail-types.js";
15
+ export { default as TimeTracker } from "../../src/work/time/time-tracker.svelte";
16
+ export { default as TimeChip } from "../../src/work/time/time-chip.svelte";
17
+ export { default as TimeRing } from "../../src/work/time/time-ring.svelte";
18
+ export { default as TimeDot } from "../../src/work/time/time-dot.svelte";
19
+ export { budgetTone, dayLabel, formatClock, formatMinutes, localDay, parseMinutes, personColor } from "./time/duration.js";
20
+ export { confidenceLevel, inboxConfidence, inboxKinds, inboxStates } from "./inbox/index.js";
21
+ export { DEFAULT_TIME_LABELS } from "./time/time-types.js";
@@ -0,0 +1,25 @@
1
+ const FRAME_PAD = 16;
2
+ export function liftDragImage(e, tilt = -3) {
3
+ const source = e.currentTarget;
4
+ if (!source || !e.dataTransfer) return;
5
+ const rect = source.getBoundingClientRect();
6
+ const frame = document.createElement("div");
7
+ Object.assign(frame.style, {
8
+ position: "fixed",
9
+ top: "-10000px",
10
+ left: "-10000px",
11
+ padding: `${FRAME_PAD}px`,
12
+ pointerEvents: "none"
13
+ });
14
+ const ghost = source.cloneNode(true);
15
+ Object.assign(ghost.style, {
16
+ width: `${rect.width}px`,
17
+ opacity: "1",
18
+ rotate: `${tilt}deg`,
19
+ filter: "drop-shadow(0 2px 4px rgb(35 35 35 / 0.08)) drop-shadow(0 10px 18px rgb(35 35 35 / 0.14))"
20
+ });
21
+ frame.appendChild(ghost);
22
+ document.body.appendChild(frame);
23
+ e.dataTransfer.setDragImage(frame, e.clientX - rect.left + FRAME_PAD, e.clientY - rect.top + FRAME_PAD);
24
+ setTimeout(()=>frame.remove());
25
+ }
File without changes
@@ -0,0 +1,35 @@
1
+ import { defineStatuses } from "../../status/define-statuses.js";
2
+ export const salesStatuses = defineStatuses({
3
+ new: {
4
+ label: "New",
5
+ tone: "accent",
6
+ variant: "open"
7
+ },
8
+ contacted: {
9
+ label: "Contacted",
10
+ tone: "info",
11
+ variant: "open"
12
+ },
13
+ proposal: {
14
+ label: "Proposal",
15
+ tone: "accent",
16
+ variant: "progress",
17
+ progress: 0.25
18
+ },
19
+ negotiation: {
20
+ label: "Negotiation",
21
+ tone: "warning",
22
+ variant: "progress",
23
+ progress: 0.75
24
+ },
25
+ won: {
26
+ label: "Won",
27
+ tone: "success",
28
+ variant: "completed"
29
+ },
30
+ lost: {
31
+ label: "Lost",
32
+ tone: "destructive",
33
+ variant: "lost"
34
+ }
35
+ });
@@ -0,0 +1,10 @@
1
+ export function reorderByIds(items, activeId, overId) {
2
+ const activeIndex = items.findIndex((item)=>item.id === activeId);
3
+ const overIndex = items.findIndex((item)=>item.id === overId);
4
+ if (activeIndex === -1 || overIndex === -1 || activeIndex === overIndex) {
5
+ return items.slice();
6
+ }
7
+ const next = items.slice();
8
+ next.splice(overIndex, 0, ...next.splice(activeIndex, 1));
9
+ return next;
10
+ }
File without changes
@@ -0,0 +1,60 @@
1
+ export function parseMinutes(text) {
2
+ const value = text.trim().toLowerCase();
3
+ if (!value) return null;
4
+ if (/^\d+$/.test(value)) return Number(value);
5
+ const clock = /^(\d+):([0-5]?\d)$/.exec(value);
6
+ if (clock) return Number(clock[1]) * 60 + Number(clock[2]);
7
+ const decimalHours = /^(\d+(?:[.,]\d+)?)\s*h$/.exec(value);
8
+ if (decimalHours?.[1]) return Math.round(Number(decimalHours[1].replace(",", ".")) * 60);
9
+ const parts = /^(?:(\d+)\s*h)?\s*(?:(\d+)\s*m?)?$/.exec(value);
10
+ if (!parts || !parts[1] && !parts[2]) return null;
11
+ return Number(parts[1] ?? 0) * 60 + Number(parts[2] ?? 0);
12
+ }
13
+ export function formatMinutes(minutes) {
14
+ const whole = Math.max(0, Math.round(Number.isFinite(minutes) ? minutes : 0));
15
+ const hours = Math.floor(whole / 60);
16
+ const rest = whole % 60;
17
+ if (hours === 0) return `${rest}m`;
18
+ return rest === 0 ? `${hours}h` : `${hours}h ${rest}m`;
19
+ }
20
+ export function formatClock(ms) {
21
+ const total = Math.max(0, Math.floor(ms / 1000));
22
+ return {
23
+ hours: String(Math.floor(total / 3600)),
24
+ minutes: String(Math.floor(total % 3600 / 60)).padStart(2, "0"),
25
+ seconds: String(total % 60).padStart(2, "0")
26
+ };
27
+ }
28
+ export function localDay(date = new Date()) {
29
+ const month = String(date.getMonth() + 1).padStart(2, "0");
30
+ const day = String(date.getDate()).padStart(2, "0");
31
+ return `${date.getFullYear()}-${month}-${day}`;
32
+ }
33
+ export function dayLabel(day, locale) {
34
+ const date = new Date(`${day}T12:00:00`);
35
+ const now = new Date();
36
+ now.setHours(12, 0, 0, 0);
37
+ const gap = Math.round((date.getTime() - now.getTime()) / 86_400_000);
38
+ if (gap === 0 || gap === -1) {
39
+ const word = new Intl.RelativeTimeFormat(locale, {
40
+ numeric: "auto"
41
+ }).format(gap, "day");
42
+ return word.charAt(0).toLocaleUpperCase(locale) + word.slice(1);
43
+ }
44
+ return date.toLocaleDateString(locale, {
45
+ weekday: "short",
46
+ month: "short",
47
+ day: "numeric"
48
+ });
49
+ }
50
+ export function budgetTone(logged, estimate) {
51
+ if (!estimate || estimate <= 0) return "neutral";
52
+ const ratio = logged / estimate;
53
+ if (ratio > 1) return "destructive";
54
+ return ratio >= 0.9 ? "warning" : "neutral";
55
+ }
56
+ export function personColor(key) {
57
+ let hash = 0;
58
+ for (const char of key)hash = (hash * 31 + char.charCodeAt(0)) % 360;
59
+ return `oklch(0.72 0.12 ${hash})`;
60
+ }
@@ -0,0 +1,25 @@
1
+ export const DEFAULT_TIME_LABELS = {
2
+ title: "Time",
3
+ timer: "Timer",
4
+ start: "Start timer",
5
+ stop: "Stop timer",
6
+ running: "Running",
7
+ since: (time)=>`Since ${time}`,
8
+ started: "Timer started",
9
+ runningFor: (duration)=>`Timer running, ${duration}`,
10
+ stopped: (duration)=>`Timer stopped, ${duration} to log`,
11
+ elapsed: "Elapsed time",
12
+ logged: "Logged",
13
+ duration: "Time spent",
14
+ durationPlaceholder: "1h30",
15
+ date: "Date worked",
16
+ note: "Note",
17
+ notePlaceholder: "What was done",
18
+ log: "Log",
19
+ saving: "Saving",
20
+ invalid: "Try 45m, 1h30 or 1.5h",
21
+ empty: "Log your first hour",
22
+ remaining: (left, estimate)=>`${left} left of ${estimate}`,
23
+ over: (over, estimate)=>`${over} over ${estimate}`,
24
+ deleteEntry: (duration)=>`Delete ${duration} entry`
25
+ };