@gjermundgaraba-designs/pixel-paper 0.16.0 → 0.17.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 +1 -1
- 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 +3 -3
- package/dist/src/sortable/sortable.d.ts.map +1 -1
- package/dist/src/sortable/sortable.js +32 -57
- package/package.json +1 -1
- package/src/pixel-paper.css +1 -13
- package/src/sortable/index.ts +1 -0
- package/src/sortable/sortable.ts +21 -58
package/DESIGN.md
CHANGED
|
@@ -1097,7 +1097,7 @@ One keyboard for the page, Vim first, with the arrows beside the letters. The ke
|
|
|
1097
1097
|
|
|
1098
1098
|
### Sortable
|
|
1099
1099
|
|
|
1100
|
-
**Sortable** (Submodel over `@foldkit/ui`'s DragAndDrop, for items the reader puts in order: a list of rows, a grid of tiles, or a grid of the page's panels) → `div.sortable (.grid, .panels)` holding `ul.sortable-items[aria-label]` (a plain list: no listbox, so an item's content may hold anything) of `li.sortable-item (.movable, .drag-dim, .drop-before, .drop-after)`, each a grip, then `div.sortable-body` with the parent's content, and the list's keyboard help in a `p.sr-only`. `"List"` (the default) prints rows edge to edge between 1px rules, for a flush panel, `8px 16px 8px 10px
|
|
1100
|
+
**Sortable** (Submodel over `@foldkit/ui`'s DragAndDrop, for items the reader puts in order: a list of rows, a grid of tiles, or a grid of the page's panels) → `div.sortable (.grid, .panels)` holding `ul.sortable-items[aria-label]` (a plain list: no listbox, so an item's content may hold anything) of `li.sortable-item (.movable, .drag-dim, .drop-before, .drop-after)`, each a grip, then `div.sortable-body` with the parent's content, and the list's keyboard help in a `p.sr-only`. `"List"` (the default) prints rows edge to edge between 1px rules, for a flush panel, `8px 16px 8px 10px`; `"Grid"` prints tiles that wrap, 180px and up, 12px apart: paper slips in a 2px ink border on the 3px print shadow. `"Panels"` prints each item as the parent's own Panel, up to three across in the deck's 24px gutter and 300px and up, so two across and then one as the column narrows; a row takes its tallest panel's height, each panel's foot sits at its bottom, and the list hands each item its grip (`render.grip`) for the panel's `lead` instead of printing it beside the item. The held copy is the whole panel, tinted head on the 8px card shadow, under ids of its own, and the drop line runs down the middle of the gutter. `isReadOnly`, for a reader who may look but not reorder, prints every grip held and lifts nothing, as holding moves does. Each item starts with a quiet `button.iconbtn` grip (in a panel's title bar, for `"Panels"`) (the grip glyph, named "Move <label>", `aria-roledescription="draggable"`, `aria-pressed`, described by the keyboard help); while moves are held it stays, held (`aria-disabled`, in the keyboard), so focus on it stays put when holding moves cancels one. Only the grip lifts an item, under a mouse, a finger or a pen (`cursor: grab` and `touch-action: none` on a movable grip only), so the rest of an item selects its text and a finger on it scrolls the page; the keyboard takes the grip too: Space or Enter picks the item up, every arrow moves it one place in reading order, Space or Enter drops it, Escape puts it back (taken before a dialog or the page's keys see it), and Tab leaves it where it is. Only the pointer that pressed moves the item; the browser cancelling it puts the item back. The held item dims to 40% in place (`.drag-dim`) and keeps its own print; a copy of it, `.lifted`, tinted head on the 8px card shadow in a 2px ink border (`aria-hidden`, `inert`, rendered with `isLifted`, so it carries no ids), follows the pointer in `div.sortable-lift`, or, held by the keyboard, prints in the list where it would land, in `li.sortable-slot`, counted as no item. Where a pointer would drop it, a 2px dashed ink line prints beside the item it lands next to (`.drop-before`, or `.drop-after` past the last), over the layout, so nothing moves under the pointer. The pointer's place is read from the item whose centre is closest, across where items sit side by side and down a column, and read again where the pointer is let go, so a page that scrolled under a still pointer drops where the pointer is. Each step is said through the page's live region in words from the item's `label` and its place, counted from one ("Beta, 3 of 4."). The items are the parent's: a drop reports `Moved`, and the parent moves the item, or decides not to, and flashes it; a drop where the item was, outside the list, or while moves are held reports nothing. While a pointer presses or carries an item the page's root carries `data-pixel-paper-dragging`, which prints the grabbing cursor everywhere and holds text selection.
|
|
1101
1101
|
|
|
1102
1102
|
### Inputs / Fields
|
|
1103
1103
|
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { AnnounceReorder, Item, Message, Model, OutMessage, SizeLiftedItem, init, setMovable, subscriptions, update, view, } from "./sortable.ts";
|
|
1
|
+
export { AnnounceReorder, Item, Message, Model, OutMessage, SizeLiftedItem, init, isHolding, setMovable, subscriptions, update, view, } from "./sortable.ts";
|
|
2
2
|
export type { InitConfig, ItemRender, Layout, ViewInputs } from "./sortable.ts";
|
|
3
3
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/sortable/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,IAAI,EACJ,OAAO,EACP,KAAK,EACL,UAAU,EACV,cAAc,EACd,IAAI,EACJ,UAAU,EACV,aAAa,EACb,MAAM,EACN,IAAI,GACL,MAAM,eAAe,CAAC;AACvB,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/sortable/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,IAAI,EACJ,OAAO,EACP,KAAK,EACL,UAAU,EACV,cAAc,EACd,IAAI,EACJ,SAAS,EACT,UAAU,EACV,aAAa,EACb,MAAM,EACN,IAAI,GACL,MAAM,eAAe,CAAC;AACvB,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { AnnounceReorder, Item, Message, Model, OutMessage, SizeLiftedItem, init, setMovable, subscriptions, update, view, } from "./sortable.js";
|
|
1
|
+
export { AnnounceReorder, Item, Message, Model, OutMessage, SizeLiftedItem, init, isHolding, setMovable, subscriptions, update, view, } from "./sortable.js";
|
|
@@ -988,9 +988,9 @@ export type ViewInputs = Readonly<{
|
|
|
988
988
|
* `li.sortable-item`, each its grip and the parent's content (a panel holds its grip in its
|
|
989
989
|
* title bar). The items are the parent's; a drop reports `Moved`.
|
|
990
990
|
*
|
|
991
|
-
*
|
|
992
|
-
*
|
|
993
|
-
* up, every arrow moves it one place in reading order, Space drops it and Escape puts it back.
|
|
991
|
+
* Only the grip lifts an item, under every pointer, so the item's own text selects and a
|
|
992
|
+
* finger on it scrolls the page; the keyboard takes the grip too: Space or Enter picks the
|
|
993
|
+
* item up, every arrow moves it one place in reading order, Space drops it and Escape puts it back.
|
|
994
994
|
* The held item dims in place; a copy, lifted onto the card shadow, follows the pointer or
|
|
995
995
|
* prints where the keyboard would drop it; each step is said through the page's live region.
|
|
996
996
|
* Lift `subscriptions(keyPrefix)` into the application's, or nothing follows the pointer or
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sortable.d.ts","sourceRoot":"","sources":["../../../src/sortable/sortable.ts"],"names":[],"mappings":"AACA,OAAO,EAAS,MAAM,EAAS,MAAM,EAAE,MAAM,EAAE,MAAM,EAAQ,MAAM,QAAQ,CAAC;AAC5E,OAAO,KAAK,OAAO,MAAM,iBAAiB,CAAC;AAC3C,OAAO,KAAK,EAAa,IAAI,EAAe,MAAM,cAAc,CAAC;AAEjE,OAAO,KAAK,KAAK,MAAM,eAAe,CAAC;AAGvC,OAAO,KAAK,YAAY,MAAM,sBAAsB,CAAC;AACrD,OAAO,KAAK,MAAM,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"sortable.d.ts","sourceRoot":"","sources":["../../../src/sortable/sortable.ts"],"names":[],"mappings":"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"}
|
|
@@ -10,7 +10,7 @@ import * as Subscription from "foldkit/subscription";
|
|
|
10
10
|
import * as Update from "foldkit/update";
|
|
11
11
|
import * as Announcer from "../announcer/announcer.js";
|
|
12
12
|
import * as Button from "../button/button.js";
|
|
13
|
-
import { LEFT_BUTTON, activatedKeyboardDrag, cancelledDrag, escapeKeys,
|
|
13
|
+
import { LEFT_BUTTON, activatedKeyboardDrag, cancelledDrag, escapeKeys, insertionIndex, isCarrying, markDragging, measureLift, movedPointer, phaseOf, pressedDraggable, releasedPointer, } from "../drag/drag.js";
|
|
14
14
|
import * as Glyph from "../glyph/glyph.js";
|
|
15
15
|
import * as IconButton from "../iconButton/iconButton.js";
|
|
16
16
|
import { LOCALE } from "../locale/locale.js";
|
|
@@ -112,7 +112,6 @@ const id = (model) => __foldkitBrandViewResult((model.dragAndDrop.id), "@gjermun
|
|
|
112
112
|
export const isHolding = (model) => __foldkitBrandViewResult((Option.isSome(UiDragAndDrop.maybeDraggedItemId(model.dragAndDrop))), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#isHolding");
|
|
113
113
|
// DOM HOOKS
|
|
114
114
|
const itemHook = (model, itemId) => __foldkitBrandViewResult((`${id(model)}/${itemId}`), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#itemHook");
|
|
115
|
-
const ITEM_ATTRIBUTE = "sortable-item";
|
|
116
115
|
const GRIP_ATTRIBUTE = "sortable-grip";
|
|
117
116
|
// COMMAND
|
|
118
117
|
/** Says a step of a move through the page's live region (as `Announcer.Announce` does). */
|
|
@@ -349,21 +348,6 @@ export const SizeLiftedItem = Mount.define("SizeLiftedItem", {
|
|
|
349
348
|
return __foldkitBrandViewResult((Message.CompletedSizeLiftedItem()), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~33");
|
|
350
349
|
})), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#execute~2"),
|
|
351
350
|
});
|
|
352
|
-
const INNER_CONTROL = innerControls(`[data-${GRIP_ATTRIBUTE}]`);
|
|
353
|
-
/** Whether a press lifts the item: on its grip under any pointer, on its body under a mouse,
|
|
354
|
-
* and never on a control inside it. */
|
|
355
|
-
const isLiftingPress = (target, pointerType) => {
|
|
356
|
-
if (!(target instanceof Element)) {
|
|
357
|
-
return __foldkitBrandViewResult((pointerType === "mouse"), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#isLiftingPress");
|
|
358
|
-
}
|
|
359
|
-
const isOnGrip = target.closest(`[data-${GRIP_ATTRIBUTE}]`) !== null;
|
|
360
|
-
const maybeItem = Option.fromNullishOr(target.closest(`[data-${ITEM_ATTRIBUTE}]`));
|
|
361
|
-
const isOnControl = Option.exists(maybeItem, (item) => {
|
|
362
|
-
const control = target.closest(INNER_CONTROL);
|
|
363
|
-
return __foldkitBrandViewResult((control !== null && item.contains(control)), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~34");
|
|
364
|
-
});
|
|
365
|
-
return __foldkitBrandViewResult((isOnGrip || (pointerType === "mouse" && !isOnControl)), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#isLiftingPress");
|
|
366
|
-
};
|
|
367
351
|
const helpId = (model) => __foldkitBrandViewResult((`${id(model)}-grip-help`), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#helpId");
|
|
368
352
|
const isHeldItem = (model, itemId) => __foldkitBrandViewResult((UiDragAndDrop.isDragging(model.dragAndDrop) &&
|
|
369
353
|
Option.contains(UiDragAndDrop.maybeDraggedItemId(model.dragAndDrop), itemHook(model, itemId))), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#isHeldItem");
|
|
@@ -378,7 +362,16 @@ const liftedView = (info, item, h) => __foldkitBrandViewResult((h.div([h.Class("
|
|
|
378
362
|
const gripView = (info, item, h) => {
|
|
379
363
|
const { model, isMovable, items } = info;
|
|
380
364
|
const isIdleNow = phaseOf(model.dragAndDrop) === "Idle";
|
|
381
|
-
const onGripKey = h.OnKeyDownPreventDefault((key) => __foldkitBrandViewResult((Option.liftPredicate(Message.PressedGripKey({ itemId: item.id, items }), () => __foldkitBrandViewResult((isIdleNow && (key === " " || key === "Enter")), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~
|
|
365
|
+
const onGripKey = h.OnKeyDownPreventDefault((key) => __foldkitBrandViewResult((Option.liftPredicate(Message.PressedGripKey({ itemId: item.id, items }), () => __foldkitBrandViewResult((isIdleNow && (key === " " || key === "Enter")), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~35"))), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~34"));
|
|
366
|
+
const onGripPress = h.OnPointerDown((_pointerType, button, screenX, screenY, _time, clientX, clientY, pointerId) => __foldkitBrandViewResult((Option.liftPredicate(Message.PressedItem({
|
|
367
|
+
itemId: item.id,
|
|
368
|
+
pointerId,
|
|
369
|
+
screenX,
|
|
370
|
+
screenY,
|
|
371
|
+
clientX,
|
|
372
|
+
clientY,
|
|
373
|
+
items,
|
|
374
|
+
}), () => __foldkitBrandViewResult((isIdleNow && button === LEFT_BUTTON), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~37"))), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~36"));
|
|
382
375
|
// NOTE: @foldkit/ui gap: DragAndDrop's `draggable` bundle forces `role="option"`, which a
|
|
383
376
|
// plain list's items are not. So the grip carries the ui's `data-draggable-id` by hand, and
|
|
384
377
|
// FocusItem finds the grip by it. While moves are held the grip stays, held, so the focus
|
|
@@ -394,62 +387,44 @@ const gripView = (info, item, h) => {
|
|
|
394
387
|
h.AriaRoleDescription("draggable"),
|
|
395
388
|
h.AriaDescribedBy(helpId(model)),
|
|
396
389
|
Button.pressedAttribute(isHeldItem(model, item.id), h),
|
|
397
|
-
...(isMovable ? [onGripKey] : []),
|
|
390
|
+
...(isMovable ? [onGripKey, onGripPress] : []),
|
|
398
391
|
],
|
|
399
392
|
}, h)), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#gripView");
|
|
400
393
|
};
|
|
401
|
-
const itemAttributes = (info, item, h) => {
|
|
402
|
-
const { model, isMovable, items } = info;
|
|
403
|
-
const isIdleNow = phaseOf(model.dragAndDrop) === "Idle";
|
|
404
|
-
const onPress = h.OnPointerDown((pointerType, button, screenX, screenY, _time, clientX, clientY, pointerId, target) => __foldkitBrandViewResult((Option.liftPredicate(Message.PressedItem({
|
|
405
|
-
itemId: item.id,
|
|
406
|
-
pointerId,
|
|
407
|
-
screenX,
|
|
408
|
-
screenY,
|
|
409
|
-
clientX,
|
|
410
|
-
clientY,
|
|
411
|
-
items,
|
|
412
|
-
}), () => __foldkitBrandViewResult((isIdleNow && isMovable && button === LEFT_BUTTON && isLiftingPress(target, pointerType)), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~38"))), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~37"));
|
|
413
|
-
return __foldkitBrandViewResult(([h.DataAttribute(ITEM_ATTRIBUTE, ""), onPress]), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#itemAttributes");
|
|
414
|
-
};
|
|
415
394
|
/** Where a pointer would drop the held item, marked on the item it would land beside: before
|
|
416
395
|
* the other item at its target, or after the last. None where it already was. */
|
|
417
|
-
const dropMarkOf = (model) => __foldkitBrandViewResult((pipe(model.maybeHeld, Option.filter(() => __foldkitBrandViewResult((phaseOf(model.dragAndDrop) === "PointerDragging"), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~
|
|
418
|
-
const others = Array.filter(held.items, (item) => __foldkitBrandViewResult((item.id !== held.item.id), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~
|
|
396
|
+
const dropMarkOf = (model) => __foldkitBrandViewResult((pipe(model.maybeHeld, Option.filter(() => __foldkitBrandViewResult((phaseOf(model.dragAndDrop) === "PointerDragging"), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~38")), Option.flatMap((held) => __foldkitBrandViewResult((pipe(targetIndex(model, held), Option.filter((index) => __foldkitBrandViewResult((!Option.contains(indexOf(held.items, held.item.id), index)), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~40")), Option.flatMap((index) => {
|
|
397
|
+
const others = Array.filter(held.items, (item) => __foldkitBrandViewResult((item.id !== held.item.id), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~42"));
|
|
419
398
|
return __foldkitBrandViewResult((Option.orElse(Option.map(Array.get(others, index), (item) => (__foldkitBrandViewResult(({
|
|
420
399
|
itemId: item.id,
|
|
421
400
|
side: "Before",
|
|
422
|
-
}), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~
|
|
401
|
+
}), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~43"))), () => __foldkitBrandViewResult((Option.map(Array.last(others), (item) => (__foldkitBrandViewResult(({
|
|
423
402
|
itemId: item.id,
|
|
424
403
|
side: "After",
|
|
425
|
-
}), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~
|
|
426
|
-
}))), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~
|
|
427
|
-
const dropClass = (info, item) => __foldkitBrandViewResult((Option.match(Option.filter(info.maybeDropMark, ({ itemId }) => __foldkitBrandViewResult((itemId === item.id), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~
|
|
404
|
+
}), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~45")))), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~44"))), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~41");
|
|
405
|
+
}))), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~39")))), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#dropMarkOf");
|
|
406
|
+
const dropClass = (info, item) => __foldkitBrandViewResult((Option.match(Option.filter(info.maybeDropMark, ({ itemId }) => __foldkitBrandViewResult((itemId === item.id), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~46")), {
|
|
428
407
|
onNone: () => __foldkitBrandViewResult((""), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#onNone~5"),
|
|
429
408
|
onSome: ({ side }) => (__foldkitBrandViewResult((side === "Before" ? " drop-before" : " drop-after"), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#onSome~5")),
|
|
430
409
|
})), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#dropClass");
|
|
431
410
|
const itemClass = (info, item) => __foldkitBrandViewResult((`sortable-item${info.isMovable ? " movable" : ""}${isHeldItem(info.model, item.id) ? " drag-dim" : ""}${dropClass(info, item)}`), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#itemClass");
|
|
432
|
-
const itemView = (info, item, h) => __foldkitBrandViewResult((h.keyed("li")(item.id, [
|
|
433
|
-
...UiDragAndDrop.sortable(itemHook(info.model, item.id)),
|
|
434
|
-
...itemAttributes(info, item, h),
|
|
435
|
-
h.Class(itemClass(info, item)),
|
|
436
|
-
], itemContents(info, item, { isLifted: false, grip: gripView(info, item, h) }, h))), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#itemView");
|
|
411
|
+
const itemView = (info, item, h) => __foldkitBrandViewResult((h.keyed("li")(item.id, [...UiDragAndDrop.sortable(itemHook(info.model, item.id)), h.Class(itemClass(info, item))], itemContents(info, item, { isLifted: false, grip: gripView(info, item, h) }, h))), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#itemView");
|
|
437
412
|
/** The items in order, with the held item's copy where the keyboard would drop it: before the
|
|
438
413
|
* other item at its target, or last. The copy carries no `data-sortable-id`, so it is not
|
|
439
414
|
* counted as an item. */
|
|
440
415
|
const itemsView = (info, h) => {
|
|
441
416
|
const { model, items } = info;
|
|
442
|
-
const rows = Array.map(items, (item) => (__foldkitBrandViewResult(({ item, html: itemView(info, item, h) }), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~
|
|
443
|
-
const maybeSlot = pipe(model.maybeHeld, Option.filter(() => __foldkitBrandViewResult((phaseOf(model.dragAndDrop) === "KeyboardDragging"), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~
|
|
417
|
+
const rows = Array.map(items, (item) => (__foldkitBrandViewResult(({ item, html: itemView(info, item, h) }), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~47")));
|
|
418
|
+
const maybeSlot = pipe(model.maybeHeld, Option.filter(() => __foldkitBrandViewResult((phaseOf(model.dragAndDrop) === "KeyboardDragging"), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~48")), Option.flatMap((held) => __foldkitBrandViewResult((Option.map(targetIndex(model, held), (index) => (__foldkitBrandViewResult(({ held, index }), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~50")))), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~49")));
|
|
444
419
|
return __foldkitBrandViewResult((Option.match(maybeSlot, {
|
|
445
|
-
onNone: () => __foldkitBrandViewResult((Array.map(rows, ({ html }) => __foldkitBrandViewResult((html), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~
|
|
420
|
+
onNone: () => __foldkitBrandViewResult((Array.map(rows, ({ html }) => __foldkitBrandViewResult((html), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~51"))), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#onNone~6"),
|
|
446
421
|
onSome: ({ held, index }) => {
|
|
447
422
|
const slot = h.keyed("li")("sortable-slot", [h.Class("sortable-slot"), h.AriaHidden(true), h.Inert(true)], [liftedView(info, held.item, h)]);
|
|
448
|
-
const others = Array.filter(rows, ({ item }) => __foldkitBrandViewResult((item.id !== held.item.id), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~
|
|
423
|
+
const others = Array.filter(rows, ({ item }) => __foldkitBrandViewResult((item.id !== held.item.id), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~52"));
|
|
449
424
|
const maybeBefore = Array.get(others, index);
|
|
450
425
|
return __foldkitBrandViewResult((Option.match(maybeBefore, {
|
|
451
|
-
onNone: () => __foldkitBrandViewResult(([...Array.map(rows, ({ html }) => __foldkitBrandViewResult((html), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~
|
|
452
|
-
onSome: (before) => __foldkitBrandViewResult((Array.flatMap(rows, ({ item, html }) => __foldkitBrandViewResult((item.id === before.item.id ? [slot, html] : [html]), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~
|
|
426
|
+
onNone: () => __foldkitBrandViewResult(([...Array.map(rows, ({ html }) => __foldkitBrandViewResult((html), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~53")), slot]), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#onNone~7"),
|
|
427
|
+
onSome: (before) => __foldkitBrandViewResult((Array.flatMap(rows, ({ item, html }) => __foldkitBrandViewResult((item.id === before.item.id ? [slot, html] : [html]), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~54"))), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#onSome~7"),
|
|
453
428
|
})), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#onSome~6");
|
|
454
429
|
},
|
|
455
430
|
})), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#itemsView");
|
|
@@ -459,7 +434,7 @@ const liftedCopyView = (info, h) => {
|
|
|
459
434
|
const maybeLifted = Option.all({
|
|
460
435
|
style: UiDragAndDrop.ghostStyle(model.dragAndDrop),
|
|
461
436
|
held: model.maybeHeld,
|
|
462
|
-
press: Option.flatMap(model.maybeHeld, ({ maybePress }) => __foldkitBrandViewResult((maybePress), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~
|
|
437
|
+
press: Option.flatMap(model.maybeHeld, ({ maybePress }) => __foldkitBrandViewResult((maybePress), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~55")),
|
|
463
438
|
});
|
|
464
439
|
return __foldkitBrandViewResult((Array.fromOption(Option.map(maybeLifted, ({ style, held, press }) => __foldkitBrandViewResult((h.div([
|
|
465
440
|
h.Class("sortable-lift"),
|
|
@@ -471,18 +446,18 @@ const liftedCopyView = (info, h) => {
|
|
|
471
446
|
pressX: press.clientX,
|
|
472
447
|
pressY: press.clientY,
|
|
473
448
|
})),
|
|
474
|
-
], [liftedView(info, held.item, h)])), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~
|
|
449
|
+
], [liftedView(info, held.item, h)])), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~56")))), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#liftedCopyView");
|
|
475
450
|
};
|
|
476
|
-
const layoutClass = (layout) => __foldkitBrandViewResult((Match.value(layout).pipe(Match.withReturnType(), Match.when("List", () => __foldkitBrandViewResult(("sortable"), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~
|
|
451
|
+
const layoutClass = (layout) => __foldkitBrandViewResult((Match.value(layout).pipe(Match.withReturnType(), Match.when("List", () => __foldkitBrandViewResult(("sortable"), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~57")), Match.when("Grid", () => __foldkitBrandViewResult(("sortable grid"), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~58")), Match.when("Panels", () => __foldkitBrandViewResult(("sortable panels"), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~59")), Match.exhaustive)), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#layoutClass");
|
|
477
452
|
/**
|
|
478
453
|
* Items the reader puts in order, as rows, as tiles or as panels, built on `@foldkit/ui`'s
|
|
479
454
|
* DragAndDrop: `div.sortable` holding `ul.sortable-items` (named by `label`) of
|
|
480
455
|
* `li.sortable-item`, each its grip and the parent's content (a panel holds its grip in its
|
|
481
456
|
* title bar). The items are the parent's; a drop reports `Moved`.
|
|
482
457
|
*
|
|
483
|
-
*
|
|
484
|
-
*
|
|
485
|
-
* up, every arrow moves it one place in reading order, Space drops it and Escape puts it back.
|
|
458
|
+
* Only the grip lifts an item, under every pointer, so the item's own text selects and a
|
|
459
|
+
* finger on it scrolls the page; the keyboard takes the grip too: Space or Enter picks the
|
|
460
|
+
* item up, every arrow moves it one place in reading order, Space drops it and Escape puts it back.
|
|
486
461
|
* The held item dims in place; a copy, lifted onto the card shadow, follows the pointer or
|
|
487
462
|
* prints where the keyboard would drop it; each step is said through the page's live region.
|
|
488
463
|
* Lift `subscriptions(keyPrefix)` into the application's, or nothing follows the pointer or
|
|
@@ -509,5 +484,5 @@ export const view = defineView((model, viewInputs, h) => {
|
|
|
509
484
|
], itemsView(info, h)),
|
|
510
485
|
h.p([h.Id(helpId(model)), h.Class("sr-only")], [COPY.gripHelp]),
|
|
511
486
|
...liftedCopyView(info, h),
|
|
512
|
-
])), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~
|
|
487
|
+
])), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~60");
|
|
513
488
|
});
|
package/package.json
CHANGED
package/src/pixel-paper.css
CHANGED
|
@@ -3369,24 +3369,16 @@ dialog.veil:focus {
|
|
|
3369
3369
|
min-width: 0;
|
|
3370
3370
|
}
|
|
3371
3371
|
|
|
3372
|
-
.sortable-item.movable {
|
|
3373
|
-
cursor: grab;
|
|
3374
|
-
}
|
|
3375
|
-
|
|
3376
3372
|
.sortable-item [data-sortable-grip] {
|
|
3377
3373
|
flex: none;
|
|
3378
3374
|
}
|
|
3379
3375
|
|
|
3376
|
+
/* the grip is the only handle: the rest of the item selects its text and scrolls the page */
|
|
3380
3377
|
.sortable-item.movable [data-sortable-grip] {
|
|
3381
3378
|
cursor: grab;
|
|
3382
|
-
/* the grip is where a finger drags; the rest of the item scrolls the page */
|
|
3383
3379
|
touch-action: none;
|
|
3384
3380
|
}
|
|
3385
3381
|
|
|
3386
|
-
.sortable-item.movable:hover {
|
|
3387
|
-
background: var(--head);
|
|
3388
|
-
}
|
|
3389
|
-
|
|
3390
3382
|
.sortable-item.drag-dim {
|
|
3391
3383
|
opacity: 0.4;
|
|
3392
3384
|
}
|
|
@@ -3489,10 +3481,6 @@ dialog.veil:focus {
|
|
|
3489
3481
|
background: none;
|
|
3490
3482
|
}
|
|
3491
3483
|
|
|
3492
|
-
.sortable.panels .sortable-item.movable:hover {
|
|
3493
|
-
background: none;
|
|
3494
|
-
}
|
|
3495
|
-
|
|
3496
3484
|
.sortable.panels .sortable-body {
|
|
3497
3485
|
height: 100%;
|
|
3498
3486
|
}
|
package/src/sortable/index.ts
CHANGED
package/src/sortable/sortable.ts
CHANGED
|
@@ -16,7 +16,6 @@ import {
|
|
|
16
16
|
activatedKeyboardDrag,
|
|
17
17
|
cancelledDrag,
|
|
18
18
|
escapeKeys,
|
|
19
|
-
innerControls,
|
|
20
19
|
insertionIndex,
|
|
21
20
|
isCarrying,
|
|
22
21
|
markDragging,
|
|
@@ -158,7 +157,6 @@ export const isHolding = (model: Model): boolean =>
|
|
|
158
157
|
|
|
159
158
|
const itemHook = (model: Model, itemId: string): string => `${id(model)}/${itemId}`;
|
|
160
159
|
|
|
161
|
-
const ITEM_ATTRIBUTE = "sortable-item";
|
|
162
160
|
const GRIP_ATTRIBUTE = "sortable-grip";
|
|
163
161
|
|
|
164
162
|
// COMMAND
|
|
@@ -596,25 +594,6 @@ export type ViewInputs = Readonly<{
|
|
|
596
594
|
toItemView: (item: Item, render: ItemRender) => ReadonlyArray<Html>;
|
|
597
595
|
}>;
|
|
598
596
|
|
|
599
|
-
const INNER_CONTROL = innerControls(`[data-${GRIP_ATTRIBUTE}]`);
|
|
600
|
-
|
|
601
|
-
/** Whether a press lifts the item: on its grip under any pointer, on its body under a mouse,
|
|
602
|
-
* and never on a control inside it. */
|
|
603
|
-
const isLiftingPress = (target: EventTarget | null, pointerType: string): boolean => {
|
|
604
|
-
if (!(target instanceof Element)) {
|
|
605
|
-
return pointerType === "mouse";
|
|
606
|
-
}
|
|
607
|
-
|
|
608
|
-
const isOnGrip = target.closest(`[data-${GRIP_ATTRIBUTE}]`) !== null;
|
|
609
|
-
const maybeItem = Option.fromNullishOr(target.closest(`[data-${ITEM_ATTRIBUTE}]`));
|
|
610
|
-
const isOnControl = Option.exists(maybeItem, (item) => {
|
|
611
|
-
const control = target.closest(INNER_CONTROL);
|
|
612
|
-
return control !== null && item.contains(control);
|
|
613
|
-
});
|
|
614
|
-
|
|
615
|
-
return isOnGrip || (pointerType === "mouse" && !isOnControl);
|
|
616
|
-
};
|
|
617
|
-
|
|
618
597
|
type ListInfo = Readonly<{
|
|
619
598
|
model: Model;
|
|
620
599
|
layout: Layout;
|
|
@@ -666,6 +645,22 @@ const gripView = (info: ListInfo, item: Item, h: HtmlBuilder<Message>): Html =>
|
|
|
666
645
|
),
|
|
667
646
|
);
|
|
668
647
|
|
|
648
|
+
const onGripPress: Attribute<Message> = h.OnPointerDown(
|
|
649
|
+
(_pointerType, button, screenX, screenY, _time, clientX, clientY, pointerId) =>
|
|
650
|
+
Option.liftPredicate(
|
|
651
|
+
Message.PressedItem({
|
|
652
|
+
itemId: item.id,
|
|
653
|
+
pointerId,
|
|
654
|
+
screenX,
|
|
655
|
+
screenY,
|
|
656
|
+
clientX,
|
|
657
|
+
clientY,
|
|
658
|
+
items,
|
|
659
|
+
}),
|
|
660
|
+
() => isIdleNow && button === LEFT_BUTTON,
|
|
661
|
+
),
|
|
662
|
+
);
|
|
663
|
+
|
|
669
664
|
// NOTE: @foldkit/ui gap: DragAndDrop's `draggable` bundle forces `role="option"`, which a
|
|
670
665
|
// plain list's items are not. So the grip carries the ui's `data-draggable-id` by hand, and
|
|
671
666
|
// FocusItem finds the grip by it. While moves are held the grip stays, held, so the focus
|
|
@@ -682,41 +677,13 @@ const gripView = (info: ListInfo, item: Item, h: HtmlBuilder<Message>): Html =>
|
|
|
682
677
|
h.AriaRoleDescription("draggable"),
|
|
683
678
|
h.AriaDescribedBy(helpId(model)),
|
|
684
679
|
Button.pressedAttribute(isHeldItem(model, item.id), h),
|
|
685
|
-
...(isMovable ? [onGripKey] : []),
|
|
680
|
+
...(isMovable ? [onGripKey, onGripPress] : []),
|
|
686
681
|
],
|
|
687
682
|
},
|
|
688
683
|
h,
|
|
689
684
|
);
|
|
690
685
|
};
|
|
691
686
|
|
|
692
|
-
const itemAttributes = (
|
|
693
|
-
info: ListInfo,
|
|
694
|
-
item: Item,
|
|
695
|
-
h: HtmlBuilder<Message>,
|
|
696
|
-
): ReadonlyArray<Attribute<Message>> => {
|
|
697
|
-
const { model, isMovable, items } = info;
|
|
698
|
-
const isIdleNow = phaseOf(model.dragAndDrop) === "Idle";
|
|
699
|
-
|
|
700
|
-
const onPress = h.OnPointerDown(
|
|
701
|
-
(pointerType, button, screenX, screenY, _time, clientX, clientY, pointerId, target) =>
|
|
702
|
-
Option.liftPredicate(
|
|
703
|
-
Message.PressedItem({
|
|
704
|
-
itemId: item.id,
|
|
705
|
-
pointerId,
|
|
706
|
-
screenX,
|
|
707
|
-
screenY,
|
|
708
|
-
clientX,
|
|
709
|
-
clientY,
|
|
710
|
-
items,
|
|
711
|
-
}),
|
|
712
|
-
() =>
|
|
713
|
-
isIdleNow && isMovable && button === LEFT_BUTTON && isLiftingPress(target, pointerType),
|
|
714
|
-
),
|
|
715
|
-
);
|
|
716
|
-
|
|
717
|
-
return [h.DataAttribute(ITEM_ATTRIBUTE, ""), onPress];
|
|
718
|
-
};
|
|
719
|
-
|
|
720
687
|
type DropMark = Readonly<{ itemId: string; side: "Before" | "After" }>;
|
|
721
688
|
|
|
722
689
|
/** Where a pointer would drop the held item, marked on the item it would land beside: before
|
|
@@ -762,11 +729,7 @@ const itemClass = (info: ListInfo, item: Item): string =>
|
|
|
762
729
|
const itemView = (info: ListInfo, item: Item, h: HtmlBuilder<Message>): Html =>
|
|
763
730
|
h.keyed("li")(
|
|
764
731
|
item.id,
|
|
765
|
-
[
|
|
766
|
-
...UiDragAndDrop.sortable(itemHook(info.model, item.id)),
|
|
767
|
-
...itemAttributes(info, item, h),
|
|
768
|
-
h.Class(itemClass(info, item)),
|
|
769
|
-
],
|
|
732
|
+
[...UiDragAndDrop.sortable(itemHook(info.model, item.id)), h.Class(itemClass(info, item))],
|
|
770
733
|
itemContents(info, item, { isLifted: false, grip: gripView(info, item, h) }, h),
|
|
771
734
|
);
|
|
772
735
|
|
|
@@ -849,9 +812,9 @@ const layoutClass = (layout: Layout): string =>
|
|
|
849
812
|
* `li.sortable-item`, each its grip and the parent's content (a panel holds its grip in its
|
|
850
813
|
* title bar). The items are the parent's; a drop reports `Moved`.
|
|
851
814
|
*
|
|
852
|
-
*
|
|
853
|
-
*
|
|
854
|
-
* up, every arrow moves it one place in reading order, Space drops it and Escape puts it back.
|
|
815
|
+
* Only the grip lifts an item, under every pointer, so the item's own text selects and a
|
|
816
|
+
* finger on it scrolls the page; the keyboard takes the grip too: Space or Enter picks the
|
|
817
|
+
* item up, every arrow moves it one place in reading order, Space drops it and Escape puts it back.
|
|
855
818
|
* The held item dims in place; a copy, lifted onto the card shadow, follows the pointer or
|
|
856
819
|
* prints where the keyboard would drop it; each step is said through the page's live region.
|
|
857
820
|
* Lift `subscriptions(keyPrefix)` into the application's, or nothing follows the pointer or
|