@daydreamui/text 0.0.0-stage → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js ADDED
@@ -0,0 +1,535 @@
1
+ import { className, createComponent, delegateEvents, effect, insert, memo, readShallow, ref, setAttribute, style, template } from "@solidjs/web";
2
+ import { Show, createEffect, createSignal, flush, onSettled, untrack } from "solid-js";
3
+ var textStyles = `
4
+ .daydream-text-item {
5
+ position: absolute;
6
+ min-width: 1rem;
7
+ min-height: 1rem;
8
+ color: var(--dream-app-canvas-text, #fff);
9
+ font-size: 1.5rem;
10
+ font-weight: 400;
11
+ line-height: 1.4;
12
+ overflow: visible;
13
+ pointer-events: auto;
14
+ }
15
+ .daydream-text-auto { width: max-content; height: max-content; }
16
+ .daydream-text-auto-height { min-height: 1lh; }
17
+ .daydream-text-content, .daydream-text-editor {
18
+ display: block;
19
+ min-width: 1rem;
20
+ min-height: 1lh;
21
+ color: inherit;
22
+ font: inherit;
23
+ overflow: visible;
24
+ overflow-wrap: anywhere;
25
+ white-space: pre-wrap;
26
+ }
27
+ .daydream-text-auto .daydream-text-content,
28
+ .daydream-text-auto .daydream-text-editor { width: max-content; white-space: pre; }
29
+ .daydream-text-content { user-select: none; }
30
+ .daydream-text-editor { outline: none; user-select: text; }
31
+ `;
32
+ function textClasses(frame, capped = false) {
33
+ return `daydream-text-item ${frame === void 0 && !capped ? "daydream-text-auto" : ""} ${frame?.height === void 0 ? "daydream-text-auto-height" : ""}`;
34
+ }
35
+ function measureNaturalTextItem(text, frame, fontSize) {
36
+ return measureText(text, frame, void 0, fontSize);
37
+ }
38
+ function measureInitialTextFrame(text, fontSize) {
39
+ if (Array.from(text).length <= 60) return void 0;
40
+ const size = measureText(text, void 0, 60, fontSize);
41
+ return size === null ? void 0 : { width: size.width };
42
+ }
43
+ function measureText(text, frame, maxWidthCh, fontSize) {
44
+ if (typeof document === "undefined" || document.body === null) return null;
45
+ const item = document.createElement("div");
46
+ item.className = textClasses(frame, maxWidthCh !== void 0);
47
+ Object.assign(item.style, {
48
+ position: "fixed",
49
+ left: "-100000px",
50
+ top: "-100000px",
51
+ visibility: "hidden",
52
+ pointerEvents: "none"
53
+ });
54
+ if (fontSize !== void 0) item.style.fontSize = `${fontSize}px`;
55
+ if (frame !== void 0) {
56
+ item.style.width = `${frame.width}px`;
57
+ if (frame.height !== void 0) item.style.height = `${frame.height}px`;
58
+ }
59
+ if (maxWidthCh !== void 0) {
60
+ item.style.width = "max-content";
61
+ item.style.maxWidth = `${maxWidthCh}ch`;
62
+ }
63
+ const content = document.createElement("div");
64
+ content.className = "daydream-text-content";
65
+ content.textContent = text;
66
+ if (text.endsWith("\n")) content.append(document.createElement("br"));
67
+ item.append(content);
68
+ document.body.append(item);
69
+ try {
70
+ const { width, height } = item.getBoundingClientRect();
71
+ return Number.isFinite(width) && Number.isFinite(height) && width > 0 && height > 0 ? {
72
+ width,
73
+ height
74
+ } : null;
75
+ } finally {
76
+ item.remove();
77
+ }
78
+ }
79
+ var TEXT_KIND = "daydream.text";
80
+ var LEGACY_TEXT_KIND = "mrbavio.text";
81
+ function isTextItem(item) {
82
+ return (item.kind === "daydream.text" || item.kind === "mrbavio.text") && textPayloadProblem(item.payload, "payload") === null;
83
+ }
84
+ function textOf(item) {
85
+ const payload = item.payload;
86
+ if (typeof payload !== "object" || payload === null) return "";
87
+ const text = payload.text;
88
+ return typeof text === "string" ? text : "";
89
+ }
90
+ function textPayloadProblem(raw, where) {
91
+ if (typeof raw !== "object" || raw === null || Array.isArray(raw)) return `${where} is not a text payload`;
92
+ const payload = raw;
93
+ if (typeof payload["text"] !== "string" || payload["text"].trim() === "") return `${where}.text must be a non-empty string`;
94
+ const fontSize = payload["fontSize"];
95
+ if (fontSize !== void 0 && (typeof fontSize !== "number" || !Number.isFinite(fontSize) || fontSize <= 0)) return `${where}.fontSize must be a positive finite number`;
96
+ if (Object.keys(payload).some((key) => key !== "text" && key !== "fontSize")) return `${where} may only contain text and fontSize`;
97
+ return null;
98
+ }
99
+ function nextTextFontSize(current, delta) {
100
+ const next = Math.max(2, current + delta);
101
+ return Number.isFinite(next) ? next : current;
102
+ }
103
+ function resizeTextFont(item, delta) {
104
+ const previous = item.payload.fontSize ?? 24;
105
+ const next = nextTextFontSize(previous, delta);
106
+ if (item.frame !== void 0) {
107
+ const width = item.frame.width * (next / previous);
108
+ if (!Number.isFinite(width) || width <= 0) return;
109
+ item.frame.width = width;
110
+ }
111
+ item.payload.fontSize = next;
112
+ }
113
+ function registerClipboard(dd) {
114
+ let consecutivePastes = 0;
115
+ let pasting = false;
116
+ let camera = untrack(() => dd.geometry.camera());
117
+ const reset = () => {
118
+ if (!pasting) consecutivePastes = 0;
119
+ };
120
+ dd.canvas.onActivity(reset);
121
+ dd.on("document", reset);
122
+ dd.on("selection", reset);
123
+ dd.on("geometry", () => {
124
+ const next = untrack(() => dd.geometry.camera());
125
+ if (next.panX !== camera.panX || next.panY !== camera.panY || next.zoom !== camera.zoom) reset();
126
+ camera = next;
127
+ });
128
+ dd.canvas.onPaste((event) => {
129
+ if ((event.clipboardData?.files.length ?? 0) > 0) return;
130
+ const text = event.clipboardData?.getData("text/plain") ?? "";
131
+ if (text.trim() === "") return;
132
+ event.preventDefault();
133
+ const cascade = consecutivePastes++ * 16;
134
+ const center = dd.canvas.center();
135
+ const frame = measureInitialTextFrame(text);
136
+ const size = measureNaturalTextItem(text, frame);
137
+ const item = {
138
+ id: dd.core.generateId(),
139
+ kind: TEXT_KIND,
140
+ position: {
141
+ x: center.x + cascade - (size?.width ?? 0) / 2,
142
+ y: center.y + cascade - (size?.height ?? 0) / 2
143
+ },
144
+ ...frame === void 0 ? {} : { frame },
145
+ payload: { text }
146
+ };
147
+ pasting = true;
148
+ try {
149
+ dd.mutateItems((items) => {
150
+ items.push(item);
151
+ });
152
+ dd.select(item.id);
153
+ flush();
154
+ } finally {
155
+ pasting = false;
156
+ }
157
+ });
158
+ dd.canvas.onCopy((event) => {
159
+ const range = window.getSelection();
160
+ if (range !== null && !range.isCollapsed) return;
161
+ const selected = dd.itemSelection();
162
+ if (selected.length !== 1 || event.clipboardData === null) return;
163
+ const item = dd.items().find((candidate) => candidate.id === selected[0]);
164
+ if (item === void 0 || !isTextItem(item)) return;
165
+ event.clipboardData.setData("text/plain", item.payload.text);
166
+ event.preventDefault();
167
+ });
168
+ }
169
+ function registerTextCommands(dd, editing) {
170
+ const soleSelectedText = () => {
171
+ const ids = dd.itemSelection();
172
+ if (ids.length !== 1) return null;
173
+ const item = dd.items().find((candidate) => candidate.id === ids[0]);
174
+ return item !== void 0 && isTextItem(item) ? item.id : null;
175
+ };
176
+ dd.registerCommand({
177
+ id: "daydream.text.edit",
178
+ title: "Edit text",
179
+ scope: "canvas",
180
+ when: () => soleSelectedText() !== null,
181
+ run: () => {
182
+ const id = soleSelectedText();
183
+ if (id === null) return false;
184
+ editing.begin(id);
185
+ }
186
+ });
187
+ dd.bindShortcut("daydream.text.edit", "Enter");
188
+ for (const direction of [-1, 1]) {
189
+ const name = direction > 0 ? "increase" : "decrease";
190
+ const keys = direction > 0 ? ["Mod++", "Mod+="] : ["Mod+-"];
191
+ for (const scope of ["canvas", "editor"]) {
192
+ const id = `daydream.text.${name}-font-size-${scope}`;
193
+ dd.registerCommand({
194
+ id,
195
+ title: `${direction > 0 ? "Increase" : "Decrease"} text size`,
196
+ scope,
197
+ when: (ctx) => scope === "editor" ? ctx.event?.target instanceof Element && ctx.event.target.closest("[data-text-editor]") !== null : dd.items().some((item) => dd.itemSelection().includes(item.id) && isTextItem(item)),
198
+ run: () => {
199
+ const delta = direction * 2;
200
+ if (scope === "editor") return editing.changeFontSize(delta);
201
+ const selected = new Set(dd.itemSelection());
202
+ dd.mutateItems((items) => {
203
+ for (const item of items) if (selected.has(item.id) && isTextItem(item)) resizeTextFont(item, delta);
204
+ });
205
+ }
206
+ });
207
+ for (const key of keys) dd.bindShortcut(id, key);
208
+ }
209
+ }
210
+ }
211
+ function createTextEditing() {
212
+ const [intent, setIntent] = createSignal(null);
213
+ const sessions = new Map();
214
+ return {
215
+ intent,
216
+ begin(id, caret = "end") {
217
+ if (untrack(intent)?.id === id) return;
218
+ setIntent({
219
+ id,
220
+ caret
221
+ });
222
+ },
223
+ end(id) {
224
+ if (id === void 0 || untrack(intent)?.id === id) setIntent(null);
225
+ },
226
+ active(id) {
227
+ return intent()?.id === id;
228
+ },
229
+ register(id, session) {
230
+ sessions.set(id, session);
231
+ return () => {
232
+ if (sessions.get(id) === session) sessions.delete(id);
233
+ };
234
+ },
235
+ commit() {
236
+ const id = intent()?.id;
237
+ if (id !== void 0) sessions.get(id)?.commit();
238
+ },
239
+ changeFontSize(delta) {
240
+ const id = intent()?.id;
241
+ const session = id === void 0 ? void 0 : sessions.get(id);
242
+ if (session === void 0) return false;
243
+ session.changeFontSize(delta);
244
+ return true;
245
+ }
246
+ };
247
+ }
248
+ function editableText(editor, terminalSentinel) {
249
+ const text = editor.innerText;
250
+ return terminalSentinel && text.endsWith("\n") ? text.slice(0, -1) : text;
251
+ }
252
+ function placeCaret(editor, caret, terminalSentinel = false) {
253
+ const selection = window.getSelection();
254
+ if (selection === null) return;
255
+ selection.removeAllRanges();
256
+ if (caret !== "end") {
257
+ const position = document.caretPositionFromPoint?.(caret.clientX, caret.clientY);
258
+ if (position != null && editor.contains(position.offsetNode)) {
259
+ const range = document.createRange();
260
+ range.setStart(position.offsetNode, position.offset);
261
+ range.collapse(true);
262
+ selection.addRange(range);
263
+ return;
264
+ }
265
+ }
266
+ const range = document.createRange();
267
+ if (terminalSentinel && editor.lastChild?.nodeType === Node.TEXT_NODE) {
268
+ const tail = editor.lastChild;
269
+ range.setStart(tail, Math.max(0, (tail.textContent?.length ?? 1) - 1));
270
+ } else range.selectNodeContents(editor);
271
+ range.collapse(false);
272
+ selection.addRange(range);
273
+ }
274
+ var _tmpl$ = template(`<div>`);
275
+ var _tmpl$2 = template(`<div class=daydream-text-editor data-text-editor data-dd-editable data-dd-native-undo contenteditable=plaintext-only spellcheck role=textbox aria-label="Canvas text"aria-multiline=true>`);
276
+ var _tmpl$3 = template(`<br aria-hidden=true>`);
277
+ var _tmpl$4 = template(`<div class=daydream-text-content><!><!>`);
278
+ function TextItemView(props) {
279
+ const dd = untrack(() => props.dd);
280
+ const editing = untrack(() => props.editing);
281
+ const itemId = untrack(() => props.item.id);
282
+ const initialPosition = untrack(() => ({ ...props.item.position }));
283
+ const onFinish = untrack(() => props.onFinish);
284
+ const findItem = () => dd.items().find((item) => item.id === itemId);
285
+ let initialText = untrack(() => textOf(props.item));
286
+ let sessionText = initialText;
287
+ let editor;
288
+ let binding;
289
+ let transaction;
290
+ let terminalSentinel = false;
291
+ const [draftFontSize, setDraftFontSize] = createSignal(24);
292
+ const currentItem = () => props.ephemeral ? findItem() ?? props.item : props.item;
293
+ const fontSize = () => {
294
+ const item = currentItem();
295
+ return isTextItem(item) ? item.payload.fontSize ?? draftFontSize() : draftFontSize();
296
+ };
297
+ const mutateText = (text) => {
298
+ if (text.trim() === "") return;
299
+ const existing = findItem();
300
+ if (existing === void 0) {
301
+ const size = draftFontSize();
302
+ transaction?.mutate((items) => {
303
+ items.push({
304
+ id: itemId,
305
+ kind: TEXT_KIND,
306
+ position: { ...initialPosition },
307
+ payload: {
308
+ text,
309
+ ...size === 24 ? {} : { fontSize: size }
310
+ }
311
+ });
312
+ });
313
+ dd.select(itemId);
314
+ } else if (textOf(existing) !== text) transaction?.update(itemId, (item) => {
315
+ if (isTextItem(item)) item.payload.text = text;
316
+ });
317
+ };
318
+ const finish = () => untrack(() => {
319
+ if (!editing.active(itemId)) return;
320
+ const value = editor === void 0 ? sessionText : editableText(editor, terminalSentinel);
321
+ if (value.trim() === "") {
322
+ if (findItem() !== void 0) {
323
+ editing.end(itemId);
324
+ transaction?.mutate((items) => {
325
+ const index = items.findIndex((item) => item.id === itemId);
326
+ if (index !== -1) items.splice(index, 1);
327
+ });
328
+ }
329
+ } else {
330
+ mutateText(value);
331
+ dd.select(itemId);
332
+ }
333
+ transaction?.commit();
334
+ transaction = void 0;
335
+ sessionText = value;
336
+ editing.end(itemId);
337
+ onFinish?.();
338
+ });
339
+ createEffect(() => editing.intent(), (intent) => {
340
+ if (intent?.id !== itemId) return;
341
+ initialText = untrack(() => textOf(props.item));
342
+ sessionText = initialText;
343
+ terminalSentinel = false;
344
+ transaction ??= dd.beginItemTransaction({ onInterrupted: () => {
345
+ transaction = void 0;
346
+ editing.end(itemId);
347
+ onFinish?.();
348
+ } });
349
+ queueMicrotask(() => {
350
+ if (editor === void 0 || !editing.active(itemId)) return;
351
+ terminalSentinel = initialText.endsWith("\n");
352
+ editor.textContent = terminalSentinel ? `${initialText}\n` : initialText;
353
+ editor.focus({ preventScroll: true });
354
+ placeCaret(editor, intent.caret, terminalSentinel);
355
+ });
356
+ });
357
+ onSettled(() => {
358
+ const unregister = editing.register(itemId, {
359
+ commit: () => finish(),
360
+ changeFontSize: (delta) => {
361
+ if (findItem() === void 0) setDraftFontSize(nextTextFontSize(draftFontSize(), delta));
362
+ else transaction?.update(itemId, (item) => {
363
+ if (isTextItem(item)) resizeTextFont(item, delta);
364
+ });
365
+ }
366
+ });
367
+ return () => untrack(() => {
368
+ unregister();
369
+ binding?.dispose();
370
+ if (editing.active(itemId)) {
371
+ transaction?.cancel();
372
+ transaction = void 0;
373
+ editing.end(itemId);
374
+ }
375
+ });
376
+ });
377
+ const boxStyle = () => ({
378
+ "font-size": `${fontSize()}px`,
379
+ left: `${props.item.position.x}px`,
380
+ top: `${props.item.position.y}px`,
381
+ ...currentItem().frame === void 0 ? {} : { width: `${currentItem().frame.width}px` },
382
+ ...currentItem().frame?.height === void 0 ? {} : { height: `${currentItem().frame.height}px` }
383
+ });
384
+ var _el$ = _tmpl$();
385
+ _el$._$$dblclick = (event) => {
386
+ event.stopPropagation();
387
+ if (!dd.canvas.panMode() && !editing.active(itemId)) {
388
+ dd.select(itemId);
389
+ editing.begin(itemId, {
390
+ clientX: event.clientX,
391
+ clientY: event.clientY
392
+ });
393
+ }
394
+ };
395
+ ref(() => {
396
+ return (node) => {
397
+ binding = dd.canvas.bindItemNode(itemId, node, { canDrag: () => !editing.active(itemId) });
398
+ };
399
+ }, _el$);
400
+ setAttribute(_el$, "data-text-item", itemId);
401
+ insert(_el$, (() => {
402
+ var _c$ = memo(() => {
403
+ return !!editing.active(itemId);
404
+ });
405
+ return () => {
406
+ return _c$() ? (() => {
407
+ var _el$2 = _tmpl$2();
408
+ _el$2._$$keydown = (event) => {
409
+ if (event.isComposing || event.keyCode === 229) return;
410
+ if (event.key === "Escape" || event.key === "Enter" && (event.metaKey || event.ctrlKey)) {
411
+ event.preventDefault();
412
+ event.stopPropagation();
413
+ finish();
414
+ }
415
+ };
416
+ _el$2.addEventListener("blur", () => finish());
417
+ _el$2._$$input = (event) => {
418
+ const inputType = event.inputType;
419
+ const rawText = event.currentTarget.innerText;
420
+ terminalSentinel = (inputType === "insertParagraph" || inputType === "insertLineBreak" || inputType === "deleteContentBackward" || inputType === "deleteContentForward" || inputType === "historyUndo" || inputType === "historyRedo") && rawText.endsWith("\n\n") || terminalSentinel && rawText.endsWith("\n");
421
+ sessionText = editableText(event.currentTarget, terminalSentinel);
422
+ mutateText(sessionText);
423
+ };
424
+ ref(() => {
425
+ return (el) => editor = el;
426
+ }, _el$2);
427
+ insert(_el$2, sessionText);
428
+ return _el$2;
429
+ })() : (() => {
430
+ var _el$3 = _tmpl$4();
431
+ var _el$4 = _el$3.firstChild;
432
+ var _el$6 = _el$4.nextSibling;
433
+ insert(_el$3, () => {
434
+ return textOf(props.item);
435
+ }, _el$4);
436
+ insert(_el$3, createComponent(Show, {
437
+ get when() {
438
+ return textOf(props.item).endsWith("\n");
439
+ },
440
+ get children() {
441
+ return _tmpl$3();
442
+ }
443
+ }), _el$6);
444
+ return _el$3;
445
+ })();
446
+ };
447
+ })());
448
+ effect(() => {
449
+ return {
450
+ e: readShallow(textClasses(currentItem().frame)),
451
+ t: readShallow(boxStyle()),
452
+ a: props.item.kind
453
+ };
454
+ }, ({ e, t, a }, _p$) => {
455
+ className(_el$, e, _p$?.e);
456
+ style(_el$, t, _p$?.t);
457
+ a !== _p$?.a && setAttribute(_el$, "data-item-kind", a);
458
+ });
459
+ return _el$;
460
+ }
461
+ delegateEvents([
462
+ "dblclick",
463
+ "input",
464
+ "keydown"
465
+ ]);
466
+ function activate(dd) {
467
+ const editing = createTextEditing();
468
+ const [draft, setDraft] = createSignal(null);
469
+ for (const kind of [TEXT_KIND, LEGACY_TEXT_KIND]) dd.registerItemKind({
470
+ kind,
471
+ payloadProblem: textPayloadProblem,
472
+ styles: textStyles,
473
+ render: (props) => createComponent(Show, {
474
+ get when() {
475
+ return draft()?.id !== props.item.id;
476
+ },
477
+ get children() {
478
+ return createComponent(TextItemView, {
479
+ dd,
480
+ editing,
481
+ get item() {
482
+ return props.item;
483
+ }
484
+ });
485
+ }
486
+ }),
487
+ describe: textOf,
488
+ title: false,
489
+ resize: {
490
+ min: 16,
491
+ max: Number.POSITIVE_INFINITY,
492
+ reset: true
493
+ },
494
+ editing: editing.active
495
+ });
496
+ dd.registerOverlay({
497
+ id: "draft",
498
+ slot: "overlay.world",
499
+ styles: textStyles,
500
+ render: () => createComponent(Show, {
501
+ get when() {
502
+ return draft();
503
+ },
504
+ children: (item) => createComponent(TextItemView, {
505
+ dd,
506
+ editing,
507
+ get item() {
508
+ return item();
509
+ },
510
+ ephemeral: true,
511
+ onFinish: () => setDraft(null)
512
+ })
513
+ })
514
+ });
515
+ dd.canvas.onEmptyDoubleClick((event, position) => {
516
+ event.preventDefault();
517
+ const item = {
518
+ id: dd.core.generateId(),
519
+ kind: TEXT_KIND,
520
+ position,
521
+ payload: { text: "" }
522
+ };
523
+ setDraft(item);
524
+ editing.begin(item.id);
525
+ });
526
+ dd.canvas.onPointerDown((event, context) => {
527
+ if (editing.intent() === null) return;
528
+ if ((event.target instanceof Element ? event.target : null)?.closest("[data-text-editor]") != null) return;
529
+ if (context.empty) event.preventDefault();
530
+ editing.commit();
531
+ });
532
+ registerClipboard(dd);
533
+ registerTextCommands(dd, editing);
534
+ }
535
+ export { activate as default };
package/icon.svg ADDED
@@ -0,0 +1,4 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke-width="1.8" stroke-linecap="square" stroke-linejoin="miter">
2
+ <path d="M10 4v10a3 3 0 0 0 3 3h3M6 8h10" stroke="#E7E5DE" stroke-width="2.5"/>
3
+ <path d="M5 21h14" stroke="#F66A2C"/>
4
+ </svg>
package/manifest.json ADDED
@@ -0,0 +1,31 @@
1
+ {
2
+ "id": "daydream.text",
3
+ "name": "Text",
4
+ "description": "Plain text notes on the canvas, outside any page.",
5
+ "version": "0.3.0",
6
+ "api": "3.1",
7
+ "contributes": {
8
+ "itemKinds": [
9
+ "daydream.text",
10
+ "mrbavio.text"
11
+ ],
12
+ "overlays": [
13
+ "draft"
14
+ ],
15
+ "commands": [
16
+ "daydream.text.edit",
17
+ "daydream.text.increase-font-size-canvas",
18
+ "daydream.text.decrease-font-size-canvas",
19
+ "daydream.text.increase-font-size-editor",
20
+ "daydream.text.decrease-font-size-editor"
21
+ ],
22
+ "shortcuts": {
23
+ "Enter": "daydream.text.edit",
24
+ "Mod++": "daydream.text.increase-font-size-canvas",
25
+ "Mod+=": "daydream.text.increase-font-size-canvas",
26
+ "Mod+-": "daydream.text.decrease-font-size-canvas"
27
+ },
28
+ "instructions": "Plain canvas annotations are provided by the Text plugin as kind daydream.text, not HTML inside a viewport. Its payload is {text: \"Hello World\"}. The text string must contain non-whitespace content and preserves newlines, repeated spaces, emoji and non-Latin text exactly. An agent adds one by writing an item of this kind into the canvas in daydream.json ({id, kind: \"daydream.text\", position, payload}). Text of 60 Unicode characters or fewer omits frame and starts auto-width; give longer text a width-only frame ({width}) of at most 60ch at its size \u2014 about 880px at the default 24px \u2014 so it wraps without truncation, never one long line. Pasted text gets that frame measured by the browser. People may resize afterward. Double-click typing starts auto-width. Existing items are not changed retroactively. Text uses the app's own typeface (system-ui with sans-serif fallbacks), regular weight, theme-aware canvas text (white in dark mode, charcoal in light), 1.4 line-height and a default 24px size. Cmd/Ctrl+plus (or equals) and Cmd/Ctrl+minus change selected or edited text by 2px down to 2px; fixed widths scale proportionally, explicit heights stay fixed and automatic heights follow the content. Keyboard-adjusted size persists as optional payload.fontSize (positive finite world pixels): omit it for new text and preserve it when round-tripping. No color, weight or typeface customization is available. canvas_state uses the exact text as the summary. The payload accepts only text and optional fontSize. Turning this plugin off preserves text items and their payloads as unknown-kind placeholders."
29
+ },
30
+ "built": "dist/index.js"
31
+ }
package/package.json CHANGED
@@ -1,6 +1,17 @@
1
1
  {
2
2
  "name": "@daydreamui/text",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.3.0",
4
+ "type": "module",
5
+ "description": "Plain text notes on the canvas, outside any page.",
6
+ "keywords": [
7
+ "daydream-plugin"
8
+ ],
9
+ "publishConfig": {
10
+ "access": "public"
11
+ },
12
+ "repository": {
13
+ "type": "git",
14
+ "url": "git+https://github.com/martinbavio/daydream-plugins.git",
15
+ "directory": "plugins/daydream.text"
16
+ }
17
+ }
package/README.md DELETED
@@ -1,3 +0,0 @@
1
- # Temporary Holding Version
2
-
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.