@joewinke/jatui 0.1.27 → 0.1.29

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 (37) hide show
  1. package/CLAUDE.md +3 -3
  2. package/LICENSE +21 -0
  3. package/dist/actions/collapse.d.ts +1 -1
  4. package/dist/actions/collapse.js +16 -30
  5. package/dist/actions/listNav.d.ts +134 -0
  6. package/dist/actions/listNav.js +643 -0
  7. package/dist/actions/railNav.js +78 -89
  8. package/dist/components/InlineEdit.svelte +26 -1
  9. package/dist/components/InlineEdit.svelte.d.ts +13 -0
  10. package/dist/components/PhoneInput.svelte +70 -20
  11. package/dist/components/PhoneInput.svelte.d.ts +5 -2
  12. package/dist/components/ResizableDivider.svelte +148 -18
  13. package/dist/components/ResizableDivider.svelte.d.ts +14 -3
  14. package/dist/components/SignaturePad.svelte +13 -6
  15. package/dist/components/SignaturePad.svelte.d.ts +1 -0
  16. package/dist/components/ThemeSelector.svelte +61 -2
  17. package/dist/components/ThemeSelector.svelte.d.ts +4 -0
  18. package/dist/components/markup.js +59 -62
  19. package/dist/components/session-nav/transcriptModel.js +49 -66
  20. package/dist/data/emojis.js +4 -4
  21. package/dist/index.d.ts +2 -0
  22. package/dist/index.js +1 -0
  23. package/dist/stores/confirmDialog.svelte.js +5 -5
  24. package/dist/stores/inputDialog.svelte.js +5 -5
  25. package/dist/types/booking.js +4 -4
  26. package/dist/types/comments.js +2 -2
  27. package/dist/types/messaging.js +3 -3
  28. package/dist/types/pipeline.js +2 -2
  29. package/dist/utils/currency.js +2 -4
  30. package/dist/utils/daisyuiColors.js +25 -27
  31. package/dist/utils/dateFormatters.js +44 -44
  32. package/dist/utils/googleMapsLoader.js +46 -100
  33. package/dist/utils/mentionParser.js +30 -30
  34. package/dist/utils/phone.js +21 -27
  35. package/dist/utils/phoneFormat.js +9 -9
  36. package/dist/utils/taskUtils.js +1 -1
  37. package/package.json +11 -5
@@ -1,6 +1,6 @@
1
1
  // Markup drawing primitives for construction drawing redlining
2
2
  // Adapted from JAT feedback annotation engine with cloud bubble tool added
3
- export var MARKUP_COLORS = [
3
+ export const MARKUP_COLORS = [
4
4
  "#ef4444",
5
5
  "#eab308",
6
6
  "#22c55e",
@@ -8,13 +8,13 @@ export var MARKUP_COLORS = [
8
8
  "#ffffff",
9
9
  "#111827",
10
10
  ];
11
- export var DEFAULT_STROKE_WIDTH = 3;
12
- var _nextId = 1;
11
+ export const DEFAULT_STROKE_WIDTH = 3;
12
+ let _nextId = 1;
13
13
  export function nextShapeId() {
14
14
  return _nextId++;
15
15
  }
16
16
  function drawArrow(ctx, shape) {
17
- var start = shape.start, end = shape.end, color = shape.color, strokeWidth = shape.strokeWidth;
17
+ const { start, end, color, strokeWidth } = shape;
18
18
  ctx.strokeStyle = color;
19
19
  ctx.lineWidth = strokeWidth;
20
20
  ctx.lineCap = "round";
@@ -24,9 +24,9 @@ function drawArrow(ctx, shape) {
24
24
  ctx.lineTo(end.x, end.y);
25
25
  ctx.stroke();
26
26
  // Arrowhead
27
- var angle = Math.atan2(end.y - start.y, end.x - start.x);
28
- var headLen = 14;
29
- var headAngle = Math.PI / 7;
27
+ const angle = Math.atan2(end.y - start.y, end.x - start.x);
28
+ const headLen = 14;
29
+ const headAngle = Math.PI / 7;
30
30
  ctx.beginPath();
31
31
  ctx.moveTo(end.x, end.y);
32
32
  ctx.lineTo(end.x - headLen * Math.cos(angle - headAngle), end.y - headLen * Math.sin(angle - headAngle));
@@ -35,24 +35,24 @@ function drawArrow(ctx, shape) {
35
35
  ctx.stroke();
36
36
  }
37
37
  function drawRectangle(ctx, shape) {
38
- var start = shape.start, end = shape.end, color = shape.color, strokeWidth = shape.strokeWidth;
38
+ const { start, end, color, strokeWidth } = shape;
39
39
  ctx.strokeStyle = color;
40
40
  ctx.lineWidth = strokeWidth;
41
41
  ctx.lineJoin = "round";
42
- var x = Math.min(start.x, end.x);
43
- var y = Math.min(start.y, end.y);
44
- var w = Math.abs(end.x - start.x);
45
- var h = Math.abs(end.y - start.y);
42
+ const x = Math.min(start.x, end.x);
43
+ const y = Math.min(start.y, end.y);
44
+ const w = Math.abs(end.x - start.x);
45
+ const h = Math.abs(end.y - start.y);
46
46
  ctx.strokeRect(x, y, w, h);
47
47
  }
48
48
  function drawEllipse(ctx, shape) {
49
- var start = shape.start, end = shape.end, color = shape.color, strokeWidth = shape.strokeWidth;
49
+ const { start, end, color, strokeWidth } = shape;
50
50
  ctx.strokeStyle = color;
51
51
  ctx.lineWidth = strokeWidth;
52
- var cx = (start.x + end.x) / 2;
53
- var cy = (start.y + end.y) / 2;
54
- var rx = Math.abs(end.x - start.x) / 2;
55
- var ry = Math.abs(end.y - start.y) / 2;
52
+ const cx = (start.x + end.x) / 2;
53
+ const cy = (start.y + end.y) / 2;
54
+ const rx = Math.abs(end.x - start.x) / 2;
55
+ const ry = Math.abs(end.y - start.y) / 2;
56
56
  if (rx < 1 || ry < 1)
57
57
  return;
58
58
  ctx.beginPath();
@@ -64,53 +64,51 @@ function drawEllipse(ctx, shape) {
64
64
  * Standard construction markup tool for highlighting areas of change.
65
65
  */
66
66
  function drawCloud(ctx, shape) {
67
- var start = shape.start, end = shape.end, color = shape.color, strokeWidth = shape.strokeWidth;
67
+ const { start, end, color, strokeWidth } = shape;
68
68
  ctx.strokeStyle = color;
69
69
  ctx.lineWidth = strokeWidth;
70
70
  ctx.lineCap = "round";
71
71
  ctx.lineJoin = "round";
72
- var x = Math.min(start.x, end.x);
73
- var y = Math.min(start.y, end.y);
74
- var w = Math.abs(end.x - start.x);
75
- var h = Math.abs(end.y - start.y);
72
+ const x = Math.min(start.x, end.x);
73
+ const y = Math.min(start.y, end.y);
74
+ const w = Math.abs(end.x - start.x);
75
+ const h = Math.abs(end.y - start.y);
76
76
  if (w < 4 || h < 4)
77
77
  return;
78
78
  // Generate perimeter points, then draw arcs between them
79
- var arcSize = Math.min(w, h, 30); // arc diameter adapts to shape size
80
- var perimeter = 2 * (w + h);
81
- var numArcs = Math.max(8, Math.round(perimeter / arcSize));
79
+ const arcSize = Math.min(w, h, 30); // arc diameter adapts to shape size
80
+ const perimeter = 2 * (w + h);
81
+ const numArcs = Math.max(8, Math.round(perimeter / arcSize));
82
82
  // Collect points along the rectangle perimeter
83
- var points = [];
84
- var segLengths = [w, h, w, h];
85
- var segDirs = [
83
+ const points = [];
84
+ const segLengths = [w, h, w, h];
85
+ const segDirs = [
86
86
  { dx: 1, dy: 0 },
87
87
  { dx: 0, dy: 1 },
88
88
  { dx: -1, dy: 0 },
89
89
  { dx: 0, dy: -1 },
90
90
  ];
91
- var segStarts = [
92
- { x: x, y: y },
93
- { x: x + w, y: y },
91
+ const segStarts = [
92
+ { x, y },
93
+ { x: x + w, y },
94
94
  { x: x + w, y: y + h },
95
- { x: x, y: y + h },
95
+ { x, y: y + h },
96
96
  ];
97
- var totalLen = 0;
98
- for (var _i = 0, segLengths_1 = segLengths; _i < segLengths_1.length; _i++) {
99
- var l = segLengths_1[_i];
97
+ let totalLen = 0;
98
+ for (const l of segLengths)
100
99
  totalLen += l;
101
- }
102
- var step = totalLen / numArcs;
103
- var dist = 0;
104
- var segIdx = 0;
105
- var segDist = 0;
106
- for (var i = 0; i < numArcs; i++) {
107
- var target = i * step;
100
+ const step = totalLen / numArcs;
101
+ let dist = 0;
102
+ let segIdx = 0;
103
+ let segDist = 0;
104
+ for (let i = 0; i < numArcs; i++) {
105
+ const target = i * step;
108
106
  while (dist + segLengths[segIdx] - segDist < target && segIdx < 3) {
109
107
  dist += segLengths[segIdx] - segDist;
110
108
  segIdx++;
111
109
  segDist = 0;
112
110
  }
113
- var remaining = target - dist;
111
+ const remaining = target - dist;
114
112
  points.push({
115
113
  x: segStarts[segIdx].x + segDirs[segIdx].dx * (segDist + remaining),
116
114
  y: segStarts[segIdx].y + segDirs[segIdx].dy * (segDist + remaining),
@@ -118,20 +116,20 @@ function drawCloud(ctx, shape) {
118
116
  }
119
117
  // Draw arcs between consecutive points
120
118
  ctx.beginPath();
121
- for (var i = 0; i < points.length; i++) {
122
- var p1 = points[i];
123
- var p2 = points[(i + 1) % points.length];
124
- var mx = (p1.x + p2.x) / 2;
125
- var my = (p1.y + p2.y) / 2;
119
+ for (let i = 0; i < points.length; i++) {
120
+ const p1 = points[i];
121
+ const p2 = points[(i + 1) % points.length];
122
+ const mx = (p1.x + p2.x) / 2;
123
+ const my = (p1.y + p2.y) / 2;
126
124
  // Bulge outward from center of rectangle
127
- var cx = x + w / 2;
128
- var cy = y + h / 2;
129
- var dx = mx - cx;
130
- var dy = my - cy;
131
- var len = Math.sqrt(dx * dx + dy * dy) || 1;
132
- var bulge = arcSize * 0.35;
133
- var ctrlX = mx + (dx / len) * bulge;
134
- var ctrlY = my + (dy / len) * bulge;
125
+ const cx = x + w / 2;
126
+ const cy = y + h / 2;
127
+ const dx = mx - cx;
128
+ const dy = my - cy;
129
+ const len = Math.sqrt(dx * dx + dy * dy) || 1;
130
+ const bulge = arcSize * 0.35;
131
+ const ctrlX = mx + (dx / len) * bulge;
132
+ const ctrlY = my + (dy / len) * bulge;
135
133
  if (i === 0) {
136
134
  ctx.moveTo(p1.x, p1.y);
137
135
  }
@@ -141,7 +139,7 @@ function drawCloud(ctx, shape) {
141
139
  ctx.stroke();
142
140
  }
143
141
  function drawFreehand(ctx, shape) {
144
- var points = shape.points, color = shape.color, strokeWidth = shape.strokeWidth;
142
+ const { points, color, strokeWidth } = shape;
145
143
  if (points.length < 2)
146
144
  return;
147
145
  ctx.strokeStyle = color;
@@ -150,16 +148,16 @@ function drawFreehand(ctx, shape) {
150
148
  ctx.lineJoin = "round";
151
149
  ctx.beginPath();
152
150
  ctx.moveTo(points[0].x, points[0].y);
153
- for (var i = 1; i < points.length; i++) {
151
+ for (let i = 1; i < points.length; i++) {
154
152
  ctx.lineTo(points[i].x, points[i].y);
155
153
  }
156
154
  ctx.stroke();
157
155
  }
158
156
  function drawText(ctx, shape) {
159
- var position = shape.position, content = shape.content, color = shape.color, fontSize = shape.fontSize;
157
+ const { position, content, color, fontSize } = shape;
160
158
  if (!content)
161
159
  return;
162
- ctx.font = "bold ".concat(fontSize, "px sans-serif");
160
+ ctx.font = `bold ${fontSize}px sans-serif`;
163
161
  ctx.textBaseline = "top";
164
162
  // Black outline for contrast on construction drawings
165
163
  ctx.strokeStyle = "#000000";
@@ -194,8 +192,7 @@ export function renderShape(ctx, shape) {
194
192
  ctx.restore();
195
193
  }
196
194
  export function renderAllShapes(ctx, shapes) {
197
- for (var _i = 0, shapes_1 = shapes; _i < shapes_1.length; _i++) {
198
- var shape = shapes_1[_i];
195
+ for (const shape of shapes) {
199
196
  renderShape(ctx, shape);
200
197
  }
201
198
  }
@@ -22,17 +22,6 @@
22
22
  * transcript shows just the headline by default and the body is
23
23
  * a drill-down. This is what keeps the left column readable.
24
24
  */
25
- var __assign = (this && this.__assign) || function () {
26
- __assign = Object.assign || function(t) {
27
- for (var s, i = 1, n = arguments.length; i < n; i++) {
28
- s = arguments[i];
29
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
30
- t[p] = s[p];
31
- }
32
- return t;
33
- };
34
- return __assign.apply(this, arguments);
35
- };
36
25
  export function rawTypeToState(raw) {
37
26
  switch (raw) {
38
27
  case 'needs_input':
@@ -48,28 +37,27 @@ export function rawTypeToState(raw) {
48
37
  }
49
38
  /** Detect a `jat-signal <type> '<json>'` invocation in a tool-call body. */
50
39
  function parseSignalBody(body) {
51
- var m = body.match(/jat-signal\s+(starting|working|needs_input|review|completing|complete|completed|paused|idle)\b/);
40
+ const m = body.match(/jat-signal\s+(starting|working|needs_input|review|completing|complete|completed|paused|idle)\b/);
52
41
  if (!m)
53
42
  return null;
54
- var label = '';
55
- var pick = body.match(/"(?:approach|question|reviewFocus|currentStep|summary|reason|taskTitle)"\s*:\s*"([^"]{3,90})/);
43
+ let label = '';
44
+ const pick = body.match(/"(?:approach|question|reviewFocus|currentStep|summary|reason|taskTitle)"\s*:\s*"([^"]{3,90})/);
56
45
  if (pick)
57
46
  label = pick[1];
58
- return { rawType: m[1], label: label };
47
+ return { rawType: m[1], label };
59
48
  }
60
49
  /** Build the linked model from rendered transcript lines. */
61
50
  export function buildLinkedSession(lines) {
62
- var items = [];
63
- var emits = [];
64
- var cur = null;
65
- var flush = function () {
51
+ const items = [];
52
+ const emits = [];
53
+ let cur = null;
54
+ const flush = () => {
66
55
  if (cur) {
67
- items.push(__assign(__assign({ id: items.length }, cur), { signalId: null }));
56
+ items.push({ id: items.length, ...cur, signalId: null });
68
57
  cur = null;
69
58
  }
70
59
  };
71
- for (var _i = 0, lines_1 = lines; _i < lines_1.length; _i++) {
72
- var line = lines_1[_i];
60
+ for (const line of lines) {
73
61
  if (!line.trim()) {
74
62
  flush();
75
63
  continue;
@@ -80,8 +68,8 @@ export function buildLinkedSession(lines) {
80
68
  continue;
81
69
  }
82
70
  if (line.startsWith('⏺ ')) {
83
- var body = line.slice(2);
84
- var sig = parseSignalBody(body);
71
+ const body = line.slice(2);
72
+ const sig = parseSignalBody(body);
85
73
  if (sig) {
86
74
  // signal emission = boundary; consume it, don't render as an item
87
75
  flush();
@@ -93,7 +81,7 @@ export function buildLinkedSession(lines) {
93
81
  continue;
94
82
  }
95
83
  if (line.startsWith(' ⎿ ')) {
96
- var body = line.slice(4);
84
+ const body = line.slice(4);
97
85
  if (cur) {
98
86
  cur.detail.push(body);
99
87
  cur.srcLines++;
@@ -102,7 +90,7 @@ export function buildLinkedSession(lines) {
102
90
  }
103
91
  if (line.startsWith(' ')) {
104
92
  // continuation: tool detail for actions, prose for prompt/assistant
105
- var body = line.trimStart();
93
+ const body = line.trimStart();
106
94
  if (cur && cur.kind === 'action') {
107
95
  cur.detail.push(body);
108
96
  cur.srcLines++;
@@ -125,21 +113,21 @@ export function buildLinkedSession(lines) {
125
113
  }
126
114
  flush();
127
115
  // Build signal nodes from emission boundaries.
128
- var signals = [];
129
- var prevBoundary = -1;
130
- emits.forEach(function (e, i) {
131
- var rowStart = Math.max(0, prevBoundary + 1);
132
- var rowEnd = Math.max(rowStart, e.afterIdx);
133
- var lineCount = 0;
134
- for (var k = rowStart; k <= rowEnd && k < items.length; k++)
116
+ const signals = [];
117
+ let prevBoundary = -1;
118
+ emits.forEach((e, i) => {
119
+ const rowStart = Math.max(0, prevBoundary + 1);
120
+ const rowEnd = Math.max(rowStart, e.afterIdx);
121
+ let lineCount = 0;
122
+ for (let k = rowStart; k <= rowEnd && k < items.length; k++)
135
123
  lineCount += items[k].srcLines;
136
124
  signals.push({
137
- id: "sig-".concat(i),
125
+ id: `sig-${i}`,
138
126
  state: rawTypeToState(e.rawType),
139
127
  rawType: e.rawType,
140
128
  label: e.label,
141
- rowStart: rowStart,
142
- rowEnd: rowEnd,
129
+ rowStart,
130
+ rowEnd,
143
131
  lineCount: Math.max(1, lineCount),
144
132
  // No WorkBlock substrate data in the raw-lines path
145
133
  blockId: null,
@@ -151,13 +139,12 @@ export function buildLinkedSession(lines) {
151
139
  });
152
140
  prevBoundary = e.afterIdx;
153
141
  });
154
- for (var _a = 0, signals_1 = signals; _a < signals_1.length; _a++) {
155
- var sig = signals_1[_a];
156
- for (var k = sig.rowStart; k <= sig.rowEnd && k < items.length; k++) {
142
+ for (const sig of signals) {
143
+ for (let k = sig.rowStart; k <= sig.rowEnd && k < items.length; k++) {
157
144
  items[k].signalId = sig.id;
158
145
  }
159
146
  }
160
- return { items: items, signals: signals };
147
+ return { items, signals };
161
148
  }
162
149
  /**
163
150
  * Build a LinkedSession from the WorkBlock substrate (B1).
@@ -175,49 +162,45 @@ export function buildLinkedSession(lines) {
175
162
  */
176
163
  export function buildLinkedSessionFromWork(blocks, items) {
177
164
  // Map WorkTranscriptItem → TranscriptItem (blockId → signalId mapping happens after)
178
- var transcriptItems = items.map(function (it) { return ({
165
+ const transcriptItems = items.map((it) => ({
179
166
  id: it.id,
180
167
  kind: it.kind,
181
168
  headline: it.headline,
182
169
  detail: it.detail,
183
170
  srcLines: it.srcLines,
184
171
  signalId: null // filled in below
185
- }); });
172
+ }));
186
173
  // Map WorkBlock → SignalNode
187
- var signals = blocks.map(function (blk) {
188
- var _a, _b, _c;
189
- return ({
190
- id: blk.id,
191
- state: rawTypeToState(blk.signal.type),
192
- rawType: blk.signal.type,
193
- label: blk.signal.label,
194
- rowStart: blk.itemRange.start,
195
- rowEnd: blk.itemRange.end,
196
- lineCount: blk.lineCount,
197
- // WorkBlock substrate fields
198
- blockId: blk.id,
199
- summary: blk.summary,
200
- filesTouched: blk.filesTouched,
201
- commits: (_a = blk.commits) !== null && _a !== void 0 ? _a : [],
202
- linesAdded: (_b = blk.linesAdded) !== null && _b !== void 0 ? _b : 0,
203
- linesRemoved: (_c = blk.linesRemoved) !== null && _c !== void 0 ? _c : 0
204
- });
205
- });
174
+ const signals = blocks.map((blk) => ({
175
+ id: blk.id,
176
+ state: rawTypeToState(blk.signal.type),
177
+ rawType: blk.signal.type,
178
+ label: blk.signal.label,
179
+ rowStart: blk.itemRange.start,
180
+ rowEnd: blk.itemRange.end,
181
+ lineCount: blk.lineCount,
182
+ // WorkBlock substrate fields
183
+ blockId: blk.id,
184
+ summary: blk.summary,
185
+ filesTouched: blk.filesTouched,
186
+ commits: blk.commits ?? [],
187
+ linesAdded: blk.linesAdded ?? 0,
188
+ linesRemoved: blk.linesRemoved ?? 0
189
+ }));
206
190
  // Assign signalId to transcript items via block ownership
207
- for (var _i = 0, signals_2 = signals; _i < signals_2.length; _i++) {
208
- var sig = signals_2[_i];
209
- for (var k = sig.rowStart; k <= sig.rowEnd && k < transcriptItems.length; k++) {
191
+ for (const sig of signals) {
192
+ for (let k = sig.rowStart; k <= sig.rowEnd && k < transcriptItems.length; k++) {
210
193
  transcriptItems[k].signalId = sig.id;
211
194
  }
212
195
  }
213
- return { items: transcriptItems, signals: signals };
196
+ return { items: transcriptItems, signals };
214
197
  }
215
198
  /**
216
199
  * A baked, realistic sample so /sankey always demos beautifully even with no live
217
200
  * session. Authored as raw transcript lines with real `jat-signal` calls, so it
218
201
  * flows through the EXACT same parser as live data.
219
202
  */
220
- export var SAMPLE_TRANSCRIPT_LINES = [
203
+ export const SAMPLE_TRANSCRIPT_LINES = [
221
204
  '',
222
205
  '› /jat:start GentleCoast jat-7h2k',
223
206
  '⏺ Bash(get-current-session-id)',
@@ -3,7 +3,7 @@
3
3
  * Each emoji has a character and searchable name.
4
4
  * Based on Unicode CLDR emoji ordering, minus most flags.
5
5
  */
6
- export var EMOJI_DATA = [
6
+ export const EMOJI_DATA = [
7
7
  {
8
8
  label: 'Smileys & Emotion',
9
9
  emojis: [
@@ -1186,11 +1186,11 @@ export var EMOJI_DATA = [
1186
1186
  },
1187
1187
  ];
1188
1188
  /** Flat array of all emojis for search */
1189
- export var ALL_EMOJIS = EMOJI_DATA.flatMap(function (g) { return g.emojis; });
1189
+ export const ALL_EMOJIS = EMOJI_DATA.flatMap((g) => g.emojis);
1190
1190
  /** Search emojis by name, returns matching entries */
1191
1191
  export function searchEmojis(query) {
1192
1192
  if (!query.trim())
1193
1193
  return [];
1194
- var terms = query.toLowerCase().split(/\s+/);
1195
- return ALL_EMOJIS.filter(function (e) { return terms.every(function (t) { return e.name.includes(t); }); });
1194
+ const terms = query.toLowerCase().split(/\s+/);
1195
+ return ALL_EMOJIS.filter((e) => terms.every((t) => e.name.includes(t)));
1196
1196
  }
package/dist/index.d.ts CHANGED
@@ -1,5 +1,7 @@
1
1
  export { railNav, createRailNav, cycle } from './actions/railNav';
2
2
  export type { RailNavOptions, RailNavController } from './actions/railNav';
3
+ export { listNav, createListNav } from './actions/listNav';
4
+ export type { ListNavOptions, ListNavController } from './actions/listNav';
3
5
  export { collapse } from './actions/collapse';
4
6
  export type { CollapseOptions } from './actions/collapse';
5
7
  export { default as Collapse } from './components/Collapse.svelte';
package/dist/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  // Actions
2
2
  export { railNav, createRailNav, cycle } from './actions/railNav';
3
+ export { listNav, createListNav } from './actions/listNav';
3
4
  export { collapse } from './actions/collapse';
4
5
  export { default as Collapse } from './components/Collapse.svelte';
5
6
  // Components — Session primitives (from JAT IDE, jat-jj79f.16 G1)
@@ -2,7 +2,7 @@
2
2
  * Global promise-based confirm dialog.
3
3
  * Usage: const ok = await showConfirm({ title: '...', body: '...' })
4
4
  */
5
- var pending = $state(null);
5
+ let pending = $state(null);
6
6
  export function getPending() {
7
7
  return pending;
8
8
  }
@@ -11,21 +11,21 @@ export function showConfirm(options) {
11
11
  if (pending) {
12
12
  pending.resolve(false);
13
13
  }
14
- return new Promise(function (resolve) {
15
- pending = { options: options, resolve: resolve };
14
+ return new Promise((resolve) => {
15
+ pending = { options, resolve };
16
16
  });
17
17
  }
18
18
  export function confirmDialog() {
19
19
  if (!pending)
20
20
  return;
21
- var p = pending;
21
+ const p = pending;
22
22
  pending = null;
23
23
  p.resolve(true);
24
24
  }
25
25
  export function cancelDialog() {
26
26
  if (!pending)
27
27
  return;
28
- var p = pending;
28
+ const p = pending;
29
29
  pending = null;
30
30
  p.resolve(false);
31
31
  }
@@ -3,7 +3,7 @@
3
3
  * Usage: const value = await showInput({ title: '...', placeholder: '...' })
4
4
  * Returns the typed string if confirmed, null if cancelled.
5
5
  */
6
- var pending = $state(null);
6
+ let pending = $state(null);
7
7
  export function getPendingInput() {
8
8
  return pending;
9
9
  }
@@ -12,21 +12,21 @@ export function showInput(options) {
12
12
  if (pending) {
13
13
  pending.resolve(null);
14
14
  }
15
- return new Promise(function (resolve) {
16
- pending = { options: options, resolve: resolve };
15
+ return new Promise((resolve) => {
16
+ pending = { options, resolve };
17
17
  });
18
18
  }
19
19
  export function submitInput(value) {
20
20
  if (!pending)
21
21
  return;
22
- var p = pending;
22
+ const p = pending;
23
23
  pending = null;
24
24
  p.resolve(value);
25
25
  }
26
26
  export function cancelInput() {
27
27
  if (!pending)
28
28
  return;
29
- var p = pending;
29
+ const p = pending;
30
30
  pending = null;
31
31
  p.resolve(null);
32
32
  }
@@ -1,7 +1,7 @@
1
1
  // Booking System Types
2
2
  // Generic types for scheduling/booking UI components
3
3
  // Day of week helpers
4
- export var DAYS_OF_WEEK = [
4
+ export const DAYS_OF_WEEK = [
5
5
  'Sunday',
6
6
  'Monday',
7
7
  'Tuesday',
@@ -10,14 +10,14 @@ export var DAYS_OF_WEEK = [
10
10
  'Friday',
11
11
  'Saturday'
12
12
  ];
13
- export var DAYS_SHORT = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
13
+ export const DAYS_SHORT = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
14
14
  // Location type display
15
- export var LOCATION_LABELS = {
15
+ export const LOCATION_LABELS = {
16
16
  remote: 'Video Call',
17
17
  phone: 'Phone Call',
18
18
  in_person: 'In Person'
19
19
  };
20
- export var LOCATION_ICONS = {
20
+ export const LOCATION_ICONS = {
21
21
  remote: 'video',
22
22
  phone: 'phone',
23
23
  in_person: 'map-pin'
@@ -6,7 +6,7 @@
6
6
  // Threading is ONE level deep on the data side: a comment is either
7
7
  // top-level (`parent_id === null`) or a single-level reply. The UI renders
8
8
  // this as two visual levels (a comment and its replies).
9
- export var COMMENT_ENTITY_TYPES = [
9
+ export const COMMENT_ENTITY_TYPES = [
10
10
  'project',
11
11
  'invoice',
12
12
  'contract',
@@ -16,7 +16,7 @@ export var COMMENT_ENTITY_TYPES = [
16
16
  'milestone',
17
17
  'contract_term'
18
18
  ];
19
- export var COMMENT_VISIBILITIES = [
19
+ export const COMMENT_VISIBILITIES = [
20
20
  'internal',
21
21
  'client'
22
22
  ];
@@ -1,7 +1,7 @@
1
1
  // Messaging System Types
2
2
  // Generic types for messaging UI components — no framework or backend dependencies
3
3
  // ─── Emoji Data Constants ─────────────────────────────────────────────
4
- export var EMOJI_CATEGORIES = [
4
+ export const EMOJI_CATEGORIES = [
5
5
  { id: 'search', name: 'Search', icon: '🔍', description: 'Search results' },
6
6
  {
7
7
  id: 'frequently_used',
@@ -59,7 +59,7 @@ export var EMOJI_CATEGORIES = [
59
59
  description: 'Organization custom emojis'
60
60
  }
61
61
  ];
62
- export var SKIN_TONES = [
62
+ export const SKIN_TONES = [
63
63
  { id: 'default', name: 'Default', unicode: '', preview: '👋' },
64
64
  { id: 'light', name: 'Light', unicode: '🏻', preview: '👋🏻' },
65
65
  { id: 'medium-light', name: 'Medium Light', unicode: '🏼', preview: '👋🏼' },
@@ -68,7 +68,7 @@ export var SKIN_TONES = [
68
68
  { id: 'dark', name: 'Dark', unicode: '🏿', preview: '👋🏿' }
69
69
  ];
70
70
  // Default quick-reaction emojis (used when no user preferences available)
71
- export var DEFAULT_QUICK_REACTIONS = [
71
+ export const DEFAULT_QUICK_REACTIONS = [
72
72
  {
73
73
  unicode: '👍',
74
74
  name: 'Thumbs Up',
@@ -1,11 +1,11 @@
1
1
  // ─── Core Stage/Column Types ───
2
2
  // ─── Defaults ───
3
- export var DEFAULT_DRAG_CONFIG = {
3
+ export const DEFAULT_DRAG_CONFIG = {
4
4
  enabled: true,
5
5
  flipDurationMs: 200,
6
6
  dropTargetClass: 'outline-dashed outline-2 outline-base-content/20'
7
7
  };
8
- export var DEFAULT_PIPELINE_CONFIG = {
8
+ export const DEFAULT_PIPELINE_CONFIG = {
9
9
  views: ['kanban'],
10
10
  defaultView: 'kanban',
11
11
  drag: DEFAULT_DRAG_CONFIG,
@@ -5,12 +5,10 @@
5
5
  * Format a number as USD currency string.
6
6
  * Override locale/currency by passing options.
7
7
  */
8
- export function formatCurrency(amount, locale, currency) {
9
- if (locale === void 0) { locale = 'en-US'; }
10
- if (currency === void 0) { currency = 'USD'; }
8
+ export function formatCurrency(amount, locale = 'en-US', currency = 'USD') {
11
9
  return new Intl.NumberFormat(locale, {
12
10
  style: 'currency',
13
- currency: currency,
11
+ currency,
14
12
  minimumFractionDigits: 2,
15
13
  maximumFractionDigits: 2
16
14
  }).format(amount);