@gjermundgaraba-designs/pixel-paper 0.22.2 → 0.24.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/DESIGN.md +18 -17
- package/dist/src/adapters/mermaid.d.ts.map +1 -1
- package/dist/src/adapters/mermaid.js +0 -24
- package/dist/src/announcer/announcer.d.ts.map +1 -1
- package/dist/src/announcer/announcer.js +12 -12
- package/dist/src/board/board.d.ts +0 -10
- package/dist/src/board/board.d.ts.map +1 -1
- package/dist/src/board/board.js +36 -64
- package/dist/src/board/index.d.ts +2 -1
- package/dist/src/board/index.d.ts.map +1 -1
- package/dist/src/board/index.js +2 -1
- package/dist/src/button/button.d.ts +1 -1
- package/dist/src/button/button.d.ts.map +1 -1
- package/dist/src/commandPalette/commandPalette.d.ts.map +1 -1
- package/dist/src/commandPalette/commandPalette.js +78 -83
- package/dist/src/commandPalette/keys.d.ts +2 -2
- package/dist/src/commandPalette/keys.d.ts.map +1 -1
- package/dist/src/commandPalette/keys.js +2 -4
- package/dist/src/commandPalette/match.d.ts.map +1 -1
- package/dist/src/commandPalette/match.js +2 -2
- package/dist/src/confirmDialog/confirmDialog.d.ts.map +1 -1
- package/dist/src/confirmDialog/confirmDialog.js +1 -2
- package/dist/src/copyButton/copyButton.d.ts +0 -5
- package/dist/src/copyButton/copyButton.d.ts.map +1 -1
- package/dist/src/copyButton/copyButton.js +2 -2
- package/dist/src/crumbs/crumbs.d.ts +0 -2
- package/dist/src/crumbs/crumbs.d.ts.map +1 -1
- package/dist/src/crumbs/crumbs.js +2 -2
- package/dist/src/dialog/dialog.d.ts +2 -0
- package/dist/src/dialog/dialog.d.ts.map +1 -1
- package/dist/src/dialog/dialog.js +3 -2
- package/dist/src/drag/drag.d.ts +28 -0
- package/dist/src/drag/drag.d.ts.map +1 -1
- package/dist/src/drag/drag.js +39 -17
- package/dist/src/editableTitle/editableTitle.d.ts +4 -4
- package/dist/src/field/field.d.ts +7 -1
- package/dist/src/field/field.d.ts.map +1 -1
- package/dist/src/field/field.js +14 -6
- package/dist/src/fieldset/fieldset.d.ts.map +1 -1
- package/dist/src/fieldset/fieldset.js +2 -4
- package/dist/src/fileTree/fileTree.d.ts.map +1 -1
- package/dist/src/fileTree/fileTree.js +16 -16
- package/dist/src/iconButton/iconButton.d.ts +6 -1
- package/dist/src/iconButton/iconButton.d.ts.map +1 -1
- package/dist/src/iconButton/iconButton.js +7 -2
- package/dist/src/inlineInput/inlineInput.d.ts +4 -0
- package/dist/src/inlineInput/inlineInput.d.ts.map +1 -1
- package/dist/src/inlineInput/inlineInput.js +9 -6
- package/dist/src/keyHelp/index.d.ts +1 -1
- package/dist/src/keyHelp/index.d.ts.map +1 -1
- package/dist/src/keyHelp/index.js +1 -1
- package/dist/src/keyHelp/keyHelp.d.ts +1 -3
- package/dist/src/keyHelp/keyHelp.d.ts.map +1 -1
- package/dist/src/keyHelp/keyHelp.js +3 -6
- package/dist/src/keyHint/keyLabel.d.ts +2 -0
- package/dist/src/keyHint/keyLabel.d.ts.map +1 -1
- package/dist/src/keyHint/keyLabel.js +3 -2
- package/dist/src/lineDiff/diff.d.ts +6 -3
- package/dist/src/lineDiff/diff.d.ts.map +1 -1
- package/dist/src/lineDiff/diff.js +40 -28
- package/dist/src/lineDiff/patch.d.ts.map +1 -1
- package/dist/src/lineDiff/patch.js +18 -13
- package/dist/src/linkState/linkState.d.ts.map +1 -1
- package/dist/src/linkState/linkState.js +1 -7
- package/dist/src/menu/slip.js +2 -2
- package/dist/src/meter/meter.d.ts.map +1 -1
- package/dist/src/meter/meter.js +22 -17
- package/dist/src/notice/notice.d.ts +2 -0
- package/dist/src/notice/notice.d.ts.map +1 -1
- package/dist/src/notice/notice.js +2 -1
- package/dist/src/panel/panel.d.ts +3 -0
- package/dist/src/panel/panel.d.ts.map +1 -1
- package/dist/src/panel/panel.js +2 -1
- package/dist/src/passwordField/passwordField.d.ts.map +1 -1
- package/dist/src/passwordField/passwordField.js +3 -7
- package/dist/src/rail/index.d.ts +1 -1
- package/dist/src/rail/index.d.ts.map +1 -1
- package/dist/src/rail/index.js +1 -1
- package/dist/src/rail/rail.d.ts +95 -20
- package/dist/src/rail/rail.d.ts.map +1 -1
- package/dist/src/rail/rail.js +103 -46
- package/dist/src/reel/layout.d.ts +9 -5
- package/dist/src/reel/layout.d.ts.map +1 -1
- package/dist/src/reel/layout.js +11 -5
- package/dist/src/reel/reel.d.ts.map +1 -1
- package/dist/src/reel/reel.js +122 -68
- package/dist/src/scheme/scheme.d.ts +1 -1
- package/dist/src/scheme/scheme.d.ts.map +1 -1
- package/dist/src/segmented/segmented.d.ts +0 -3
- package/dist/src/segmented/segmented.d.ts.map +1 -1
- package/dist/src/segmented/segmented.js +1 -6
- package/dist/src/selectField/selectField.d.ts.map +1 -1
- package/dist/src/selectField/selectField.js +3 -10
- package/dist/src/sortable/index.d.ts +1 -1
- package/dist/src/sortable/index.d.ts.map +1 -1
- package/dist/src/sortable/index.js +1 -1
- package/dist/src/sortable/sortable.d.ts +39 -40
- package/dist/src/sortable/sortable.d.ts.map +1 -1
- package/dist/src/sortable/sortable.js +14 -31
- package/dist/src/stack/stack.d.ts +1 -1
- package/dist/src/stack/stack.d.ts.map +1 -1
- package/dist/src/stack/stack.js +1 -1
- package/dist/src/tabs/tabs.d.ts +1 -1
- package/dist/src/tabs/tabs.d.ts.map +1 -1
- package/dist/src/tabs/tabs.js +1 -1
- package/dist/src/textareaField/textareaField.d.ts.map +1 -1
- package/dist/src/textareaField/textareaField.js +3 -7
- package/dist/src/time/time.d.ts.map +1 -1
- package/dist/src/time/time.js +4 -2
- package/dist/src/tips/index.d.ts +1 -1
- package/dist/src/tips/index.d.ts.map +1 -1
- package/dist/src/tips/tips.d.ts +30 -1
- package/dist/src/tips/tips.d.ts.map +1 -1
- package/dist/src/tips/tips.js +53 -31
- package/dist/src/toast/index.d.ts +1 -1
- package/dist/src/toast/index.d.ts.map +1 -1
- package/dist/src/toast/toast.d.ts +5 -5
- package/dist/src/toast/toast.d.ts.map +1 -1
- package/dist/src/toast/toast.js +1 -6
- package/dist/src/toolbar/toolbar.d.ts +0 -3
- package/dist/src/toolbar/toolbar.d.ts.map +1 -1
- package/dist/src/toolbar/toolbar.js +1 -2
- package/package.json +1 -1
- package/src/adapters/mermaid.ts +0 -24
- package/src/announcer/announcer.ts +13 -17
- package/src/board/board.ts +32 -80
- package/src/board/index.ts +1 -1
- package/src/button/button.ts +1 -1
- package/src/commandPalette/commandPalette.ts +21 -38
- package/src/commandPalette/keys.ts +2 -4
- package/src/commandPalette/match.ts +3 -3
- package/src/confirmDialog/confirmDialog.ts +5 -3
- package/src/copyButton/copyButton.ts +2 -5
- package/src/crumbs/crumbs.ts +2 -4
- package/src/dialog/dialog.ts +3 -2
- package/src/drag/drag.ts +54 -5
- package/src/field/field.ts +29 -7
- package/src/fieldset/fieldset.ts +2 -4
- package/src/fileTree/fileTree.ts +10 -12
- package/src/iconButton/iconButton.ts +19 -2
- package/src/inlineInput/inlineInput.ts +11 -2
- package/src/keyHelp/index.ts +0 -1
- package/src/keyHelp/keyHelp.ts +3 -9
- package/src/keyHint/keyLabel.ts +5 -2
- package/src/lineDiff/diff.ts +70 -54
- package/src/lineDiff/patch.ts +27 -14
- package/src/linkState/linkState.ts +1 -8
- package/src/menu/slip.ts +2 -2
- package/src/meter/meter.ts +25 -15
- package/src/notice/notice.ts +2 -1
- package/src/panel/panel.ts +5 -0
- package/src/passwordField/passwordField.ts +3 -7
- package/src/pixel-paper.css +200 -134
- package/src/rail/index.ts +2 -0
- package/src/rail/rail.ts +124 -44
- package/src/reel/layout.ts +14 -7
- package/src/reel/reel.ts +132 -63
- package/src/scheme/scheme.ts +1 -1
- package/src/segmented/segmented.ts +1 -9
- package/src/selectField/selectField.ts +3 -10
- package/src/sortable/index.ts +0 -1
- package/src/sortable/sortable.ts +35 -54
- package/src/stack/stack.ts +1 -1
- package/src/tabs/tabs.ts +1 -1
- package/src/textareaField/textareaField.ts +3 -7
- package/src/time/time.ts +6 -7
- package/src/tips/index.ts +1 -1
- package/src/tips/tips.ts +71 -35
- package/src/toast/index.ts +1 -1
- package/src/toast/toast.ts +2 -8
- package/src/tokens.css +7 -0
- package/src/toolbar/toolbar.ts +0 -5
- package/dist/src/inlineInput/inline.d.ts +0 -6
- package/dist/src/inlineInput/inline.d.ts.map +0 -1
- package/dist/src/inlineInput/inline.js +0 -7
- package/src/inlineInput/inline.ts +0 -13
package/src/tips/tips.ts
CHANGED
|
@@ -1,4 +1,15 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
Array,
|
|
3
|
+
Duration,
|
|
4
|
+
Effect,
|
|
5
|
+
Equal,
|
|
6
|
+
Match,
|
|
7
|
+
Number,
|
|
8
|
+
Option,
|
|
9
|
+
Schema,
|
|
10
|
+
Stream,
|
|
11
|
+
pipe,
|
|
12
|
+
} from "effect";
|
|
2
13
|
import * as Command from "foldkit/command";
|
|
3
14
|
import * as Dom from "foldkit/dom";
|
|
4
15
|
import type { Html } from "foldkit/html";
|
|
@@ -23,7 +34,10 @@ type Side = typeof Side.Type;
|
|
|
23
34
|
export const Trigger = Schema.Literals(["Pointer", "Focus"]);
|
|
24
35
|
export type Trigger = typeof Trigger.Type;
|
|
25
36
|
|
|
26
|
-
|
|
37
|
+
/** What a tip says: its control's name, and the key that does the same where the control
|
|
38
|
+
* names one (`data-tip-key`). */
|
|
39
|
+
const Words = { text: Schema.String, maybeKey: Schema.Option(Schema.String), side: Side };
|
|
40
|
+
type Words = Readonly<{ text: string; maybeKey: Option.Option<string>; side: Side }>;
|
|
27
41
|
const ShownWords = { ...Words, trigger: Trigger };
|
|
28
42
|
|
|
29
43
|
/** Where the page's tip is. `Cold`: none lately. `Waiting`: a pointer rests on a control, for
|
|
@@ -51,10 +65,10 @@ export type Model = typeof Model.Type;
|
|
|
51
65
|
|
|
52
66
|
/** Union of all Messages the tip layer can produce. */
|
|
53
67
|
export const Message = defineMessageUnion({
|
|
54
|
-
EnteredTipTarget:
|
|
68
|
+
EnteredTipTarget: Words,
|
|
55
69
|
LeftTipTarget: {},
|
|
56
70
|
EnteredTip: {},
|
|
57
|
-
FocusedTipTarget:
|
|
71
|
+
FocusedTipTarget: Words,
|
|
58
72
|
BlurredTipTarget: {},
|
|
59
73
|
PressedPointer: {},
|
|
60
74
|
PressedKey: {},
|
|
@@ -103,6 +117,9 @@ const WARMTH = Duration.millis(400);
|
|
|
103
117
|
/** The attribute that holds a control's tip: its accessible name. */
|
|
104
118
|
const TIP_ATTRIBUTE = "data-tip";
|
|
105
119
|
|
|
120
|
+
/** The attribute that holds the key a control's tip prints after its name. */
|
|
121
|
+
const TIP_KEY_ATTRIBUTE = "data-tip-key";
|
|
122
|
+
|
|
106
123
|
const TIP_SELECTOR = `[${TIP_ATTRIBUTE}]`;
|
|
107
124
|
|
|
108
125
|
const hasText = (element: HTMLElement, text: string): boolean =>
|
|
@@ -204,9 +221,11 @@ export const WaitBeforeCooling = Command.define("WaitBeforeCooling", {
|
|
|
204
221
|
|
|
205
222
|
type UpdateReturn = Update.Return<Model, Message>;
|
|
206
223
|
|
|
207
|
-
const
|
|
208
|
-
|
|
209
|
-
|
|
224
|
+
const wordsOf = ({ text, maybeKey, side }: Words): Words => ({ text, maybeKey, side });
|
|
225
|
+
|
|
226
|
+
const show = (model: Model, words: Words, trigger: Trigger): UpdateReturn => ({
|
|
227
|
+
model: modifyFields(model, { state: () => TipState.Shown({ ...wordsOf(words), trigger }) }),
|
|
228
|
+
commands: [ShowTip({ tipId: model.id, text: words.text, trigger })],
|
|
210
229
|
});
|
|
211
230
|
|
|
212
231
|
const hide = (model: Model): UpdateReturn => {
|
|
@@ -217,12 +236,12 @@ const hide = (model: Model): UpdateReturn => {
|
|
|
217
236
|
};
|
|
218
237
|
};
|
|
219
238
|
|
|
220
|
-
const wait = (model: Model,
|
|
239
|
+
const wait = (model: Model, words: Words): UpdateReturn => {
|
|
221
240
|
const nextVersion = Number.increment(model.version);
|
|
222
241
|
return {
|
|
223
242
|
model: modifyFields(model, {
|
|
224
243
|
version: () => nextVersion,
|
|
225
|
-
state: () => TipState.Waiting(
|
|
244
|
+
state: () => TipState.Waiting(wordsOf(words)),
|
|
226
245
|
}),
|
|
227
246
|
commands: [WaitBeforeShowing({ version: nextVersion })],
|
|
228
247
|
};
|
|
@@ -233,7 +252,7 @@ const leave = (model: Model, shown: typeof TipState.Shown.Type): UpdateReturn =>
|
|
|
233
252
|
return {
|
|
234
253
|
model: modifyFields(model, {
|
|
235
254
|
version: () => nextVersion,
|
|
236
|
-
state: () => TipState.Leaving({
|
|
255
|
+
state: () => TipState.Leaving({ ...wordsOf(shown), trigger: shown.trigger }),
|
|
237
256
|
}),
|
|
238
257
|
commands: [WaitBeforeHiding({ version: nextVersion })],
|
|
239
258
|
};
|
|
@@ -253,26 +272,26 @@ const dismiss = (model: Model): UpdateReturn =>
|
|
|
253
272
|
Warm: () => ({ model }),
|
|
254
273
|
});
|
|
255
274
|
|
|
256
|
-
const entered = (model: Model,
|
|
275
|
+
const entered = (model: Model, words: Words): UpdateReturn =>
|
|
257
276
|
TipState.match<UpdateReturn>(model.state, {
|
|
258
|
-
Cold: () => wait(model,
|
|
259
|
-
Waiting: (waiting) => (waiting.text === text ? { model } : wait(model,
|
|
260
|
-
Shown: (shown) => (shown.text === text ? { model } : show(model,
|
|
277
|
+
Cold: () => wait(model, words),
|
|
278
|
+
Waiting: (waiting) => (waiting.text === words.text ? { model } : wait(model, words)),
|
|
279
|
+
Shown: (shown) => (shown.text === words.text ? { model } : show(model, words, "Pointer")),
|
|
261
280
|
Leaving: (leaving) =>
|
|
262
|
-
leaving.text === text
|
|
281
|
+
leaving.text === words.text
|
|
263
282
|
? {
|
|
264
283
|
model: modifyFields(model, {
|
|
265
|
-
state: () => TipState.Shown({
|
|
284
|
+
state: () => TipState.Shown({ ...wordsOf(words), trigger: leaving.trigger }),
|
|
266
285
|
}),
|
|
267
286
|
}
|
|
268
|
-
: show(model,
|
|
269
|
-
Warm: () => show(model,
|
|
287
|
+
: show(model, words, "Pointer"),
|
|
288
|
+
Warm: () => show(model, words, "Pointer"),
|
|
270
289
|
});
|
|
271
290
|
|
|
272
291
|
/** Processes a tip layer Message and returns the next Model and Commands. */
|
|
273
292
|
export const update = (model: Model, message: Message) =>
|
|
274
293
|
Message.match<UpdateReturn>(message, {
|
|
275
|
-
EnteredTipTarget: (
|
|
294
|
+
EnteredTipTarget: (words) => entered(model, wordsOf(words)),
|
|
276
295
|
LeftTipTarget: () =>
|
|
277
296
|
TipState.matchOrElse<UpdateReturn>(
|
|
278
297
|
model.state,
|
|
@@ -286,13 +305,15 @@ export const update = (model: Model, message: Message) =>
|
|
|
286
305
|
TipState.matchOrElse<UpdateReturn>(
|
|
287
306
|
model.state,
|
|
288
307
|
{
|
|
289
|
-
Leaving: (
|
|
290
|
-
model: modifyFields(model, {
|
|
308
|
+
Leaving: (leaving) => ({
|
|
309
|
+
model: modifyFields(model, {
|
|
310
|
+
state: () => TipState.Shown({ ...wordsOf(leaving), trigger: leaving.trigger }),
|
|
311
|
+
}),
|
|
291
312
|
}),
|
|
292
313
|
},
|
|
293
314
|
() => ({ model }),
|
|
294
315
|
),
|
|
295
|
-
FocusedTipTarget: (
|
|
316
|
+
FocusedTipTarget: (words) => show(model, wordsOf(words), "Focus"),
|
|
296
317
|
BlurredTipTarget: () => dismiss(model),
|
|
297
318
|
PressedPointer: () => dismiss(model),
|
|
298
319
|
PressedKey: () => dismiss(model),
|
|
@@ -300,8 +321,8 @@ export const update = (model: Model, message: Message) =>
|
|
|
300
321
|
TipState.matchOrElse<UpdateReturn>(
|
|
301
322
|
model.state,
|
|
302
323
|
{
|
|
303
|
-
Waiting: (
|
|
304
|
-
model.version === version ? show(model,
|
|
324
|
+
Waiting: (waiting) =>
|
|
325
|
+
model.version === version ? show(model, wordsOf(waiting), "Pointer") : { model },
|
|
305
326
|
},
|
|
306
327
|
() => ({ model }),
|
|
307
328
|
),
|
|
@@ -328,10 +349,15 @@ type TargetMessage =
|
|
|
328
349
|
| typeof Message.LeftTipTarget.Type
|
|
329
350
|
| typeof Message.EnteredTip.Type;
|
|
330
351
|
|
|
331
|
-
type TipTarget = Readonly<{ element: HTMLElement
|
|
352
|
+
type TipTarget = Words & Readonly<{ element: HTMLElement }>;
|
|
332
353
|
|
|
354
|
+
/** A control in a vertical strip of tools, or set in vertical writing (a folded rail's title
|
|
355
|
+
* bar), takes its tip at its side, where the tip would cover the next tool or the top bar. */
|
|
333
356
|
const sideOf = (element: Element): Side =>
|
|
334
|
-
element.closest('[aria-orientation="vertical"]') === null
|
|
357
|
+
element.closest('[aria-orientation="vertical"]') === null &&
|
|
358
|
+
!getComputedStyle(element).writingMode.startsWith("vertical")
|
|
359
|
+
? "Top"
|
|
360
|
+
: "Right";
|
|
335
361
|
|
|
336
362
|
const tipTargetOf = (target: EventTarget | null): Option.Option<TipTarget> =>
|
|
337
363
|
pipe(
|
|
@@ -341,6 +367,7 @@ const tipTargetOf = (target: EventTarget | null): Option.Option<TipTarget> =>
|
|
|
341
367
|
Option.map(Option.fromNullishOr(element.getAttribute(TIP_ATTRIBUTE)), (text) => ({
|
|
342
368
|
element,
|
|
343
369
|
text,
|
|
370
|
+
maybeKey: Option.fromNullishOr(element.getAttribute(TIP_KEY_ATTRIBUTE)),
|
|
344
371
|
side: sideOf(element),
|
|
345
372
|
})),
|
|
346
373
|
),
|
|
@@ -366,7 +393,7 @@ export const pointerOverMessage = (
|
|
|
366
393
|
return Option.some(
|
|
367
394
|
Option.match(tipTargetOf(event.target), {
|
|
368
395
|
onNone: () => Message.LeftTipTarget(),
|
|
369
|
-
onSome: (
|
|
396
|
+
onSome: (target) => Message.EnteredTipTarget(wordsOf(target)),
|
|
370
397
|
}),
|
|
371
398
|
);
|
|
372
399
|
};
|
|
@@ -376,7 +403,7 @@ export const pointerOverMessage = (
|
|
|
376
403
|
const focusInMessage = (event: FocusEvent): Option.Option<Message> =>
|
|
377
404
|
Option.map(
|
|
378
405
|
Option.filter(tipTargetOf(event.target), ({ element }) => element.matches(":focus-visible")),
|
|
379
|
-
(
|
|
406
|
+
(target) => Message.FocusedTipTarget(wordsOf(target)),
|
|
380
407
|
);
|
|
381
408
|
|
|
382
409
|
/** Focus leaving a control with a tip, not into a part of itself, closes the tip (and
|
|
@@ -421,7 +448,9 @@ const pointerOverChanges = (tipId: string): Stream.Stream<Message> =>
|
|
|
421
448
|
const sameWords = (previous: Message, next: Message): boolean =>
|
|
422
449
|
previous._tag !== "EnteredTipTarget" ||
|
|
423
450
|
next._tag !== "EnteredTipTarget" ||
|
|
424
|
-
(previous.text === next.text &&
|
|
451
|
+
(previous.text === next.text &&
|
|
452
|
+
previous.side === next.side &&
|
|
453
|
+
Equal.equals(previous.maybeKey, next.maybeKey));
|
|
425
454
|
|
|
426
455
|
const tipSubscriptions = Subscription.make<Model, Message>()((entry) => ({
|
|
427
456
|
pointerAndFocus: entry(
|
|
@@ -480,16 +509,17 @@ export const subscriptions = <Prefix extends string>(keyPrefix: Prefix) =>
|
|
|
480
509
|
|
|
481
510
|
// VIEW
|
|
482
511
|
|
|
483
|
-
const
|
|
512
|
+
const maybeWordsOf = (model: Model): Option.Option<Words> =>
|
|
484
513
|
Match.value(model.state).pipe(
|
|
485
|
-
Match.withReturnType<Option.Option<
|
|
486
|
-
Match.tag("Waiting", "Shown", "Leaving", (
|
|
514
|
+
Match.withReturnType<Option.Option<Words>>(),
|
|
515
|
+
Match.tag("Waiting", "Shown", "Leaving", (words) => Option.some(wordsOf(words))),
|
|
487
516
|
Match.orElse(() => Option.none()),
|
|
488
517
|
);
|
|
489
518
|
|
|
490
519
|
/**
|
|
491
520
|
* The page's one tip: `div.tip[popover="manual"][aria-hidden="true"]`, which shows the words
|
|
492
|
-
* of any control carrying `data-tip` (IconButton, the glyph switch, a board's grip)
|
|
521
|
+
* of any control carrying `data-tip` (IconButton, the glyph switch, a board's grip), then the
|
|
522
|
+
* key in its `data-tip-key` where it has one (an IconButton's `keyHint`). Render it
|
|
493
523
|
* once, beside the Announcer, and lift `subscriptions(keyPrefix)`. It opens on a resting
|
|
494
524
|
* pointer after a moment (at once while another has just closed), never on touch, and on
|
|
495
525
|
* keyboard focus; it can be hovered; leaving, blur, a press or any key closes it, and Escape
|
|
@@ -501,7 +531,7 @@ const wordsOf = (model: Model): Option.Option<Readonly<{ text: string; side: Sid
|
|
|
501
531
|
* accessibility tree, and any control takes one by carrying `data-tip`.
|
|
502
532
|
*/
|
|
503
533
|
export const view = defineView<Model, Message>((model, h): Html => {
|
|
504
|
-
const maybeWords =
|
|
534
|
+
const maybeWords = maybeWordsOf(model);
|
|
505
535
|
|
|
506
536
|
return h.div(
|
|
507
537
|
[
|
|
@@ -513,6 +543,12 @@ export const view = defineView<Model, Message>((model, h): Html => {
|
|
|
513
543
|
? [h.DataAttribute("side", "right")]
|
|
514
544
|
: []),
|
|
515
545
|
],
|
|
516
|
-
Option.
|
|
546
|
+
Option.match(maybeWords, {
|
|
547
|
+
onNone: () => [],
|
|
548
|
+
onSome: ({ text, maybeKey }) => [
|
|
549
|
+
text,
|
|
550
|
+
...Array.fromOption(Option.map(maybeKey, (key) => h.kbd([h.Class("key-hint")], [key]))),
|
|
551
|
+
],
|
|
552
|
+
}),
|
|
517
553
|
);
|
|
518
554
|
});
|
package/src/toast/index.ts
CHANGED
|
@@ -13,6 +13,6 @@ export {
|
|
|
13
13
|
update,
|
|
14
14
|
view,
|
|
15
15
|
} from "./toast.ts";
|
|
16
|
-
export type { InitConfig, ShowConfig
|
|
16
|
+
export type { InitConfig, ShowConfig } from "./toast.ts";
|
|
17
17
|
export type { Action, Tone } from "./stack.ts";
|
|
18
18
|
export { Focus } from "../focus/focus.ts";
|
package/src/toast/toast.ts
CHANGED
|
@@ -295,7 +295,7 @@ const oldestCalm = (model: Model): Option.Option<Stack.Entry> => {
|
|
|
295
295
|
|
|
296
296
|
/** What `show` returns: the next Model and Commands, and the new slip's id, to take it back
|
|
297
297
|
* with `dismiss`. */
|
|
298
|
-
|
|
298
|
+
type ShowReturn = Update.Return<Model, Message> & Readonly<{ entryId: string }>;
|
|
299
299
|
|
|
300
300
|
const spoken = (config: ShowConfig): string =>
|
|
301
301
|
config.body === undefined ? `${config.title}.` : `${config.title}. ${config.body}`;
|
|
@@ -350,17 +350,11 @@ export const dismiss = (model: Model, entryId: string): StepReturn =>
|
|
|
350
350
|
|
|
351
351
|
// VIEW
|
|
352
352
|
|
|
353
|
-
const TONE_CLASS: Record<Tone, string> = {
|
|
354
|
-
Ok: "notice toast ok",
|
|
355
|
-
Error: "notice toast error",
|
|
356
|
-
Quiet: "notice toast quiet",
|
|
357
|
-
};
|
|
358
|
-
|
|
359
353
|
const slipView = (entry: Stack.Entry, h: HtmlBuilder<Message>): Html => {
|
|
360
354
|
const { tone, title, maybeBody, maybeAction } = entry.payload;
|
|
361
355
|
|
|
362
356
|
return h.div(
|
|
363
|
-
[h.Class(TONE_CLASS[tone])],
|
|
357
|
+
[h.Class(`notice toast${Notice.TONE_CLASS[tone]}`)],
|
|
364
358
|
[
|
|
365
359
|
Notice.toneGlyphView({ tone }, h),
|
|
366
360
|
h.div([], [h.strong([], [title]), ...Option.toArray(maybeBody)]),
|
package/src/tokens.css
CHANGED
|
@@ -81,6 +81,11 @@
|
|
|
81
81
|
conic-gradient(at 1px 1px, #0000 75%, var(--dither-dot) 0) 0 0 / 4px 4px,
|
|
82
82
|
conic-gradient(at 1px 1px, #0000 75%, var(--dither-dot) 0) 2px 2px / 4px 4px, var(--dither-base);
|
|
83
83
|
|
|
84
|
+
/* ---------- colour: fades ---------- */
|
|
85
|
+
--fade-on-ink: 0.75; /* what prints muted on paper, printed in paper on an inverted fill */
|
|
86
|
+
--fade-held: 0.6; /* a held control on an ink title bar */
|
|
87
|
+
--fade-dragged: 0.4; /* a held item, dimmed in place while its copy follows the pointer */
|
|
88
|
+
|
|
84
89
|
/* ---------- type: three families ---------- */
|
|
85
90
|
--font-px: "Departure Mono", ui-monospace, Menlo, Monaco, monospace;
|
|
86
91
|
--font-body: system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
|
|
@@ -122,6 +127,7 @@
|
|
|
122
127
|
--deck: 1160px; /* the widest a deck of panels runs */
|
|
123
128
|
--rail: 272px; /* the column of panels beside a deck, until the reader sizes it */
|
|
124
129
|
--rail-drawer: 320px; /* the rail as a drawer, whatever width the reader gave it */
|
|
130
|
+
--rail-folded: 64px; /* the rail folded to its first panel's bar, stood on end */
|
|
125
131
|
|
|
126
132
|
/* ---------- space: between components (Stack, Group, Wrap) ---------- */
|
|
127
133
|
--space-s: 8px; /* things in one line: buttons, chips, a glyph and its word */
|
|
@@ -147,6 +153,7 @@
|
|
|
147
153
|
|
|
148
154
|
/* ---------- the bench: a page whose work is the window ---------- */
|
|
149
155
|
--bench-work-min: 152px; /* the least of its height the work keeps: a 120px pane, 16px gutters */
|
|
156
|
+
--bench-head-min: 64px; /* the least of its head a short window keeps: its padding and a small button */
|
|
150
157
|
|
|
151
158
|
/* ---------- charts ---------- */
|
|
152
159
|
--chart-plot: 160px; /* a line chart's plot, between its top line and its axis */
|
package/src/toolbar/toolbar.ts
CHANGED
|
@@ -4,7 +4,6 @@ import type { Html, HtmlBuilder } from "foldkit/html";
|
|
|
4
4
|
import { defineMessageUnion } from "foldkit/message";
|
|
5
5
|
import * as Mount from "foldkit/mount";
|
|
6
6
|
|
|
7
|
-
import type { Attributes } from "../attributes/attributes.ts";
|
|
8
7
|
import { isPlain } from "../keys/keys.ts";
|
|
9
8
|
|
|
10
9
|
// MODEL
|
|
@@ -172,8 +171,6 @@ export type ViewConfig<ParentMessage> = Readonly<{
|
|
|
172
171
|
* Scene, resolve the Mount by name with the lifted Message:
|
|
173
172
|
* `Scene.Mount.resolve({ name: Toolbar.BindToolKeys.name }, toParentMessage(Toolbar.Message.MovedToolFocus({ move })))`. */
|
|
174
173
|
toParentMessage: (message: Message) => ParentMessage;
|
|
175
|
-
/** Further attributes for the toolbar, never a class. */
|
|
176
|
-
attributes?: Attributes<ParentMessage>;
|
|
177
174
|
}>;
|
|
178
175
|
|
|
179
176
|
/** A strip of tools that is one stop for Tab (`role="toolbar"`, named by its label, with its
|
|
@@ -189,12 +186,10 @@ export const view = <ParentMessage>(
|
|
|
189
186
|
orientation = "Horizontal",
|
|
190
187
|
isFloating = false,
|
|
191
188
|
toParentMessage,
|
|
192
|
-
attributes = [],
|
|
193
189
|
} = config;
|
|
194
190
|
|
|
195
191
|
return h.div(
|
|
196
192
|
[
|
|
197
|
-
...attributes,
|
|
198
193
|
h.Role("toolbar"),
|
|
199
194
|
h.AriaLabel(label),
|
|
200
195
|
h.AriaOrientation(orientation === "Vertical" ? "vertical" : "horizontal"),
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import { Option } from "effect";
|
|
2
|
-
/** What Enter or leaving an inline field writes: the draft trimmed, or none (an untouched
|
|
3
|
-
* draft, so an edit made elsewhere to `value` is never overwritten; an empty one; or the
|
|
4
|
-
* text it replaces). */
|
|
5
|
-
export declare const toWrite: (maybeDraft: Option.Option<string>, value: string) => Option.Option<string>;
|
|
6
|
-
//# sourceMappingURL=inline.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"inline.d.ts","sourceRoot":"","sources":["../../../src/inlineInput/inline.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAgB,MAAM,QAAQ,CAAC;AAI9C;;yBAEyB;AACzB,eAAO,MAAM,OAAO,eAAgB,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,MAAM,KAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAK5F,CAAC"}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import { brandViewResult as __foldkitBrandViewResult } from 'foldkit/brand'
|
|
2
|
-
import { Option, String, pipe } from "effect";
|
|
3
|
-
// RULES
|
|
4
|
-
/** What Enter or leaving an inline field writes: the draft trimmed, or none (an untouched
|
|
5
|
-
* draft, so an edit made elsewhere to `value` is never overwritten; an empty one; or the
|
|
6
|
-
* text it replaces). */
|
|
7
|
-
export const toWrite = (maybeDraft, value) => __foldkitBrandViewResult((pipe(maybeDraft, Option.map(String.trim), Option.filter((text) => __foldkitBrandViewResult((String.isNonEmpty(text) && text !== value), "@gjermundgaraba-designs/pixel-paper/src/inlineInput/inline.js#anonymous")))), "@gjermundgaraba-designs/pixel-paper/src/inlineInput/inline.js#toWrite");
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { Option, String, pipe } from "effect";
|
|
2
|
-
|
|
3
|
-
// RULES
|
|
4
|
-
|
|
5
|
-
/** What Enter or leaving an inline field writes: the draft trimmed, or none (an untouched
|
|
6
|
-
* draft, so an edit made elsewhere to `value` is never overwritten; an empty one; or the
|
|
7
|
-
* text it replaces). */
|
|
8
|
-
export const toWrite = (maybeDraft: Option.Option<string>, value: string): Option.Option<string> =>
|
|
9
|
-
pipe(
|
|
10
|
-
maybeDraft,
|
|
11
|
-
Option.map(String.trim),
|
|
12
|
-
Option.filter((text) => String.isNonEmpty(text) && text !== value),
|
|
13
|
-
);
|