@dxos/react-list 0.1.23 → 0.1.41

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 (47) hide show
  1. package/README.md +1 -22
  2. package/dist/lib/browser/index.mjs +147 -493
  3. package/dist/lib/browser/index.mjs.map +4 -4
  4. package/dist/lib/browser/meta.json +1 -1
  5. package/dist/lib/node/index.cjs +229 -0
  6. package/dist/lib/node/index.cjs.map +7 -0
  7. package/dist/lib/node/meta.json +1 -0
  8. package/dist/types/src/List.d.ts +42 -0
  9. package/dist/types/src/List.d.ts.map +1 -0
  10. package/dist/types/src/ListItem.d.ts +56 -0
  11. package/dist/types/src/ListItem.d.ts.map +1 -0
  12. package/dist/types/src/index.d.ts +2 -2
  13. package/dist/types/src/index.d.ts.map +1 -1
  14. package/package.json +24 -18
  15. package/src/List.tsx +87 -0
  16. package/src/ListItem.tsx +228 -0
  17. package/src/index.ts +2 -2
  18. package/dist/types/src/components/List/List.d.ts +0 -8
  19. package/dist/types/src/components/List/List.d.ts.map +0 -1
  20. package/dist/types/src/components/List/List.stories.d.ts +0 -17
  21. package/dist/types/src/components/List/List.stories.d.ts.map +0 -1
  22. package/dist/types/src/components/List/index.d.ts +0 -2
  23. package/dist/types/src/components/List/index.d.ts.map +0 -1
  24. package/dist/types/src/components/ListPrimitive/ListPrimitive.d.ts +0 -55
  25. package/dist/types/src/components/ListPrimitive/ListPrimitive.d.ts.map +0 -1
  26. package/dist/types/src/components/ListPrimitive/ListPrimitive.stories.d.ts +0 -31
  27. package/dist/types/src/components/ListPrimitive/ListPrimitive.stories.d.ts.map +0 -1
  28. package/dist/types/src/components/ListPrimitive/index.d.ts +0 -2
  29. package/dist/types/src/components/ListPrimitive/index.d.ts.map +0 -1
  30. package/dist/types/src/components/index.d.ts +0 -2
  31. package/dist/types/src/components/index.d.ts.map +0 -1
  32. package/dist/types/src/hooks/index.d.ts +0 -2
  33. package/dist/types/src/hooks/index.d.ts.map +0 -1
  34. package/dist/types/src/hooks/usePropStatefully.d.ts +0 -6
  35. package/dist/types/src/hooks/usePropStatefully.d.ts.map +0 -1
  36. package/dist/types/src/model.d.ts +0 -3
  37. package/dist/types/src/model.d.ts.map +0 -1
  38. package/src/components/List/List.stories.tsx +0 -123
  39. package/src/components/List/List.tsx +0 -111
  40. package/src/components/List/index.ts +0 -5
  41. package/src/components/ListPrimitive/ListPrimitive.stories.tsx +0 -41
  42. package/src/components/ListPrimitive/ListPrimitive.tsx +0 -474
  43. package/src/components/ListPrimitive/index.ts +0 -5
  44. package/src/components/index.ts +0 -5
  45. package/src/hooks/index.ts +0 -5
  46. package/src/hooks/usePropStatefully.ts +0 -33
  47. package/src/model.ts +0 -6
package/README.md CHANGED
@@ -1,22 +1 @@
1
- # @dxos/react-list
2
-
3
- A list editing experience component for DXOS.
4
-
5
- ## Installation
6
-
7
- ```bash
8
- pnpm i @dxos/react-list
9
- ```
10
-
11
- ## DXOS Resources
12
-
13
- - [Website](https://dxos.org)
14
- - [Developer Documentation](https://docs.dxos.org)
15
- - Tag [questions on Stack Overflow](https://stackoverflow.com/questions/tagged/dxos) with `#dxos`
16
- - Tag us on twitter [`@dxos_org`](https://twitter.com/dxos_org)
17
-
18
- ## Contributions
19
-
20
- Your ideas, issues, and code are most welcome. Please take a look at our [community code of conduct](https://github.com/dxos/dxos/blob/main/CODE_OF_CONDUCT.md), the [issue guide](https://github.com/dxos/dxos/blob/main/CONTRIBUTING.md#submitting-issues), and the [PR contribution guide](https://github.com/dxos/dxos/blob/main/CONTRIBUTING.md#submitting-prs). If you would like to contribute to the design and implementation of DXOS, please [start with the contributor's guide](https://github.com/dxos/dxos/blob/main/CONTRIBUTING.md).
21
-
22
- License: [MIT](./LICENSE) Copyright 2022 © DXOS
1
+ # DXOS `react-list` primitive
@@ -1,46 +1,11 @@
1
- // packages/apps/patterns/react-list/src/components/List/List.tsx
2
- import React2, { useCallback as useCallback2 } from "react";
3
- import { ObjectModel } from "@dxos/object-model";
4
- import { useSelection, useSpace } from "@dxos/react-client";
5
- import { Loading, useTranslation as useTranslation2 } from "@dxos/react-components";
6
-
7
- // packages/apps/patterns/react-list/src/model.ts
8
- var LIST_TYPE = "dxos:type/list";
9
- var LIST_ITEM_TYPE = "dxos:type/list-item";
10
-
11
- // packages/apps/patterns/react-list/src/components/ListPrimitive/ListPrimitive.tsx
12
- import debounce from "lodash.debounce";
13
- import { Minus, Plus } from "phosphor-react";
14
- import React, { useCallback, useMemo, useState as useState2 } from "react";
15
- import { defaultFocus, Input, useTranslation, getSize, Button, randomString as randomString2, defaultGroup, defaultHover, mx } from "@dxos/react-components";
16
-
17
- // packages/apps/patterns/react-list/src/hooks/usePropStatefully.ts
18
- import { useEffect, useRef, useState } from "react";
19
- import { randomString } from "@dxos/react-components";
20
- var isEqual = (a, b) => a === b;
21
- var usePropStatefully = (propsValue, equivalentPredicate) => {
22
- const [value, setValue] = useState(propsValue);
23
- const [valueSession, setValueSession] = useState(randomString());
24
- const mounted = useRef(false);
25
- const predicate = equivalentPredicate != null ? equivalentPredicate : isEqual;
26
- useEffect(() => {
27
- if (mounted.current && !predicate(propsValue, value)) {
28
- setValue(propsValue);
29
- setValueSession(randomString());
30
- } else {
31
- mounted.current = true;
32
- }
33
- }, [
34
- propsValue
35
- ]);
36
- return [
37
- value,
38
- setValue,
39
- valueSession
40
- ];
41
- };
42
-
43
- // packages/apps/patterns/react-list/src/components/ListPrimitive/ListPrimitive.tsx
1
+ // packages/ui/primitives/react-list/src/List.tsx
2
+ import { DndContext } from "@dnd-kit/core";
3
+ import { restrictToVerticalAxis } from "@dnd-kit/modifiers";
4
+ import { SortableContext, arrayMove } from "@dnd-kit/sortable";
5
+ import { createContextScope } from "@radix-ui/react-context";
6
+ import { Primitive } from "@radix-ui/react-primitive";
7
+ import omit from "lodash.omit";
8
+ import React, { forwardRef } from "react";
44
9
  function _extends() {
45
10
  _extends = Object.assign || function(target) {
46
11
  for (var i = 1; i < arguments.length; i++) {
@@ -55,386 +20,44 @@ function _extends() {
55
20
  };
56
21
  return _extends.apply(this, arguments);
57
22
  }
58
- var isListItemChangedAction = (o) => "listItemId" in o;
59
- var isListItemCreatedAction = (o) => "created" in o;
60
- var isListItemDeletedAction = (o) => "deleted" in o;
61
- var defaultCreateListItemId = async () => randomString2(8);
62
- var ListItemPrimitive = ({ id, title: propsTitle, description: propsDescription, annotations: propsAnnotations, updateItem, deleteItem, createItem, updateOrder, orderIndex, isLast, autoFocus }) => {
63
- const checkId = `${id}__checkbox`;
64
- const labelId = `${id}__title`;
65
- const descriptionId = `${id}__description`;
66
- const { t } = useTranslation("appkit");
67
- const rejectTextUpdatesWhenFocused = useCallback((a, b) => {
68
- var _a;
69
- return ((_a = document.activeElement) == null ? void 0 : _a.getAttribute("data-itemid")) === id ? true : a === b;
70
- }, [
71
- id
72
- ]);
73
- const [title, setTitle, titleSession] = usePropStatefully(propsTitle != null ? propsTitle : "", rejectTextUpdatesWhenFocused);
74
- const [description, _setDescription, _descriptionSession] = usePropStatefully(propsDescription != null ? propsDescription : "", rejectTextUpdatesWhenFocused);
75
- const [annotations, setAnnotations] = useState2(propsAnnotations != null ? propsAnnotations : {});
76
- const isDone = (annotations == null ? void 0 : annotations.state) === "done";
77
- const onChangeTitle = useCallback((nextValue) => {
78
- setTitle(nextValue);
79
- updateItem({
80
- id,
81
- title: nextValue
82
- });
83
- }, []);
84
- const _onChangeDescription = useCallback((nextValue) => {
85
- _setDescription(nextValue);
86
- updateItem({
87
- id,
88
- description: nextValue
89
- });
90
- }, []);
91
- const _onClickMoveUp = useCallback(() => {
92
- updateOrder(id, -1);
93
- }, [
94
- updateOrder,
95
- id
96
- ]);
97
- const _onClickMoveDown = useCallback(() => {
98
- updateOrder(id, 1);
99
- }, [
100
- updateOrder,
101
- id
102
- ]);
103
- const onChangeCheckbox = useCallback(() => {
104
- const nextAnnotations = {
105
- ...annotations,
106
- state: isDone ? "init" : "done"
107
- };
108
- setAnnotations(nextAnnotations);
109
- updateItem({
110
- id,
111
- annotations: nextAnnotations
112
- });
113
- }, [
114
- annotations,
115
- isDone
116
- ]);
117
- const onClickDelete = useCallback(() => {
118
- deleteItem(id);
119
- }, [
120
- deleteItem,
121
- id
122
- ]);
123
- const onKeyUp = useCallback((e) => {
124
- var _a, _b, _c;
125
- switch (e.key) {
126
- case "Enter":
127
- if (!e.shiftKey) {
128
- if (isLast) {
129
- createItem();
130
- } else {
131
- (_a = document.querySelector(`input[data-orderindex="${orderIndex + 1}"]`)) == null ? void 0 : _a.focus();
132
- }
133
- }
134
- break;
135
- case "PageDown":
136
- (_b = document.querySelector(`input[data-orderindex="${orderIndex + 1}"]`)) == null ? void 0 : _b.focus();
137
- break;
138
- case "PageUp":
139
- (_c = document.querySelector(`input[data-orderindex="${orderIndex - 1}"]`)) == null ? void 0 : _c.focus();
140
- break;
141
- }
142
- }, [
143
- orderIndex,
144
- isLast
145
- ]);
146
- const inputSlots = useMemo(() => ({
147
- root: {
148
- className: "m-0"
149
- },
150
- input: {
151
- className: "border-0 rounded",
152
- autoFocus: true,
153
- "data-orderindex": orderIndex,
154
- "data-itemid": id,
155
- onKeyUp
156
- }
157
- }), [
158
- orderIndex,
159
- id,
160
- onKeyUp
161
- ]);
162
- return /* @__PURE__ */ React.createElement("li", _extends({
163
- key: id,
164
- className: "flex items-center gap-2 pli-4 mbe-2",
165
- "aria-labelledby": labelId
166
- }, description && {
167
- "aria-describedby": descriptionId
168
- }), /* @__PURE__ */ React.createElement("input", _extends({}, {
169
- type: "checkbox",
170
- id: checkId,
171
- ...description && {
172
- "aria-describedby": descriptionId
173
- },
174
- className: mx(getSize(5), "text-primary-600 bg-neutral-50 rounded-full border-neutral-300 dark:bg-neutral-800 dark:border-neutral-600 cursor-pointer", defaultFocus, defaultHover({})),
175
- onChange: onChangeCheckbox,
176
- checked: isDone
177
- })), /* @__PURE__ */ React.createElement("label", {
178
- htmlFor: checkId,
179
- id: labelId,
180
- className: "sr-only"
181
- }, title), /* @__PURE__ */ React.createElement("span", {
182
- id: descriptionId,
183
- className: "sr-only"
184
- }, description), /* @__PURE__ */ React.createElement("div", {
185
- role: "none",
186
- className: "grow"
187
- }, /* @__PURE__ */ React.createElement(Input, {
188
- key: titleSession,
189
- label: t("list item title label"),
190
- placeholder: t("list item title placeholder"),
191
- labelVisuallyHidden: true,
192
- initialValue: title,
193
- onChange: onChangeTitle,
194
- slots: inputSlots
195
- })), /* @__PURE__ */ React.createElement(Button, {
196
- onClick: onClickDelete,
197
- variant: "ghost",
198
- className: "p-1 self-stretch"
199
- }, /* @__PURE__ */ React.createElement(Minus, {
200
- className: getSize(4)
201
- }), /* @__PURE__ */ React.createElement("span", {
202
- className: "sr-only"
203
- }, t("delete list item label"))));
204
- };
205
- var itemsEquivalent = (a, b) => {
206
- var _a, _b;
207
- const aKeys = Object.keys(a);
208
- const bKeys = Object.keys(b);
209
- for (let i = 0; i < aKeys.length; i++) {
210
- const key = aKeys[i];
211
- if (key !== bKeys[i] || a[key].title !== b[key].title || ((_a = a[key].annotations) == null ? void 0 : _a.state) !== ((_b = b[key].annotations) == null ? void 0 : _b.state)) {
212
- return false;
213
- }
214
- }
215
- return true;
216
- };
217
- var ListPrimitive = ({ id: listId, title: propsTitle, description: propsDescription, items: propsItems, onAction, createListItemId = defaultCreateListItemId, onChangePeriod = 0, ...divProps }) => {
218
- const { t } = useTranslation("appkit");
219
- const [creating, setCreating] = useState2(false);
220
- const [autoFocus, setAutofocus] = useState2(null);
221
- const rejectTextUpdatesWhenFocused = useCallback((a, b) => {
222
- var _a;
223
- return ((_a = document.activeElement) == null ? void 0 : _a.getAttribute("data-itemid")) === listId ? true : a === b;
224
- }, [
225
- listId
226
- ]);
227
- const titleId = `${listId}__title`;
228
- const [title, setTitle, titleSession] = usePropStatefully(propsTitle != null ? propsTitle : "", rejectTextUpdatesWhenFocused);
229
- const propagateTitle = useCallback((nextValue) => {
230
- return onAction == null ? void 0 : onAction({
231
- listId,
232
- next: {
233
- title: nextValue
234
- }
235
- });
236
- }, [
237
- onAction
238
- ]);
239
- const debouncedPropagateTitle = useMemo(() => debounce(propagateTitle, onChangePeriod), [
240
- propagateTitle
241
- ]);
242
- const onChangeTitle = useCallback((nextValue) => {
243
- setTitle(nextValue);
244
- debouncedPropagateTitle(nextValue);
245
- }, [
246
- onAction,
247
- listId
248
- ]);
249
- const descriptionId = `${listId}__description`;
250
- const [description, setDescription, _descriptionSession] = usePropStatefully(propsDescription != null ? propsDescription : "", rejectTextUpdatesWhenFocused);
251
- const propagateDescription = useCallback((nextValue) => onAction == null ? void 0 : onAction({
252
- listId,
253
- next: {
254
- description: nextValue
255
- }
256
- }), [
257
- onAction
258
- ]);
259
- const debouncedPropagateDescription = useMemo(() => debounce(propagateDescription, onChangePeriod), [
260
- propagateDescription
261
- ]);
262
- const _onChangeDescription = useCallback((nextValue) => {
263
- setDescription(nextValue);
264
- debouncedPropagateDescription(nextValue);
265
- }, [
266
- onAction,
267
- listId
268
- ]);
269
- const [items, setItems, itemsSession] = usePropStatefully(propsItems != null ? propsItems : {}, itemsEquivalent);
270
- const order = Object.keys(items);
271
- const propagateItem = useCallback(({ id, ...next }) => {
272
- return onAction == null ? void 0 : onAction({
273
- listId,
274
- listItemId: id,
275
- next
276
- });
277
- }, [
278
- listId,
279
- onAction
280
- ]);
281
- const debouncedPropagateItem = useMemo(() => debounce(propagateItem, onChangePeriod), [
282
- propagateItem
283
- ]);
284
- const updateItem = useCallback(({ id, ...next }) => {
285
- setItems(Object.assign(items, {
286
- [id]: {
287
- ...items[id],
288
- ...next
289
- }
290
- }));
291
- "title" in next && debouncedPropagateItem({
292
- id,
293
- title: next.title
294
- });
295
- "description" in next && debouncedPropagateItem({
296
- id,
297
- description: next.description
298
- });
299
- "annotations" in next && (onAction == null ? void 0 : onAction({
300
- listId,
301
- listItemId: id,
302
- next: {
303
- annotations: next.annotations
304
- }
305
- }));
306
- }, [
307
- items,
308
- listId,
309
- onAction
310
- ]);
311
- const updateOrder = useCallback((id, delta) => {
312
- const fromIndex = order.indexOf(id);
313
- const toIndex = fromIndex + delta;
314
- const nextOrder = Array.from(order);
315
- nextOrder.splice(fromIndex, 1);
316
- nextOrder.splice(toIndex, 0, id);
317
- const nextItems = nextOrder.reduce((acc, listItemId) => {
318
- acc[listItemId] = items[listItemId];
319
- return acc;
320
- }, {});
321
- setItems(nextItems);
322
- onAction == null ? void 0 : onAction({
323
- listId,
324
- next: {}
325
- });
326
- }, [
327
- items,
328
- onAction
329
- ]);
330
- const deleteItem = useCallback((id) => {
331
- if (items[id]) {
332
- const { [id]: deletedItem, ...nextItems } = items;
333
- setItems(nextItems);
334
- onAction == null ? void 0 : onAction({
335
- listId,
336
- next: {},
337
- deleted: {
338
- id,
339
- ...deletedItem
340
- }
341
- });
342
- }
343
- }, [
344
- items,
345
- onAction
346
- ]);
347
- const createItem = useCallback(() => {
348
- setCreating(true);
349
- return createListItemId().then((id) => {
350
- const next = {
351
- items: {
352
- ...items,
353
- [id]: {}
354
- }
355
- };
356
- const created = {
357
- id
358
- };
359
- setItems(next.items);
360
- setAutofocus(id);
361
- onAction == null ? void 0 : onAction({
362
- listId,
363
- next: {},
364
- created
365
- });
366
- }).finally(() => setCreating(false));
367
- }, [
368
- items,
369
- createListItemId,
370
- onAction
371
- ]);
372
- const inputSlots = useMemo(() => ({
373
- root: {
374
- className: "mli-2 mbs-0 mbe-2"
375
- },
376
- input: {
377
- className: "border-0 rounded text-xl font-display font-semibold",
378
- "data-itemid": listId
379
- }
380
- }), [
381
- listId
382
- ]);
383
- return /* @__PURE__ */ React.createElement("div", _extends({
384
- role: "group"
385
- }, divProps, {
386
- className: mx(defaultGroup({
387
- elevation: 3,
388
- spacing: "pbs-2 pbe-1"
389
- }), divProps.className),
390
- "aria-labelledby": titleId
391
- }, description && {
392
- "aria-describedby": descriptionId
393
- }), /* @__PURE__ */ React.createElement("span", {
394
- id: titleId,
395
- className: "sr-only"
396
- }, title), description && /* @__PURE__ */ React.createElement("span", {
397
- id: descriptionId,
398
- className: "sr-only"
399
- }, description), /* @__PURE__ */ React.createElement(Input, {
400
- key: titleSession,
401
- label: t("list title label"),
402
- placeholder: t("list title placeholder"),
403
- labelVisuallyHidden: true,
404
- initialValue: title,
405
- onChange: onChangeTitle,
406
- slots: inputSlots
407
- }), /* @__PURE__ */ React.createElement("ol", {
408
- className: "contents"
409
- }, order.map((listItemId, index) => {
410
- return /* @__PURE__ */ React.createElement(ListItemPrimitive, _extends({
411
- key: `${itemsSession}__${listItemId}`,
412
- orderIndex: index,
413
- isLast: index === order.length - 1
414
- }, {
415
- id: listItemId,
416
- updateItem,
417
- updateOrder,
418
- deleteItem,
419
- createItem
420
- }, items[listItemId], {
421
- autoFocus: listItemId === autoFocus
422
- }));
423
- })), /* @__PURE__ */ React.createElement("div", {
424
- role: "none",
425
- className: "mli-4 mlb-4"
426
- }, /* @__PURE__ */ React.createElement(Button, {
427
- className: "is-full",
428
- onClick: createItem,
429
- disabled: creating
430
- }, /* @__PURE__ */ React.createElement(Plus, {
431
- className: getSize(5)
432
- }), /* @__PURE__ */ React.createElement("span", {
433
- className: "sr-only"
434
- }, t("add list item label")))));
435
- };
23
+ var LIST_NAME = "List";
24
+ var [createListContext, createListScope] = createContextScope(LIST_NAME, []);
25
+ var [ListProvider, useListContext] = createListContext(LIST_NAME);
26
+ var List = /* @__PURE__ */ forwardRef((props, forwardedRef) => {
27
+ const { __listScope, variant = "ordered", selectable = false, toggleOpenLabel = "Expand/collapse item", children, ...rootProps } = props;
28
+ const ListRoot = variant === "ordered" || variant === "ordered-draggable" ? Primitive.ol : Primitive.ul;
29
+ return /* @__PURE__ */ React.createElement(ListRoot, _extends({}, selectable && {
30
+ role: "listbox",
31
+ "aria-multiselectable": true
32
+ }, omit(rootProps, "onDragEnd", "listItemIds"), {
33
+ ref: forwardedRef
34
+ }), /* @__PURE__ */ React.createElement(ListProvider, _extends({}, {
35
+ scope: __listScope,
36
+ variant,
37
+ selectable,
38
+ toggleOpenLabel
39
+ }), variant === "ordered-draggable" ? /* @__PURE__ */ React.createElement(DndContext, {
40
+ onDragEnd: props.onDragEnd,
41
+ modifiers: [
42
+ restrictToVerticalAxis
43
+ ]
44
+ }, /* @__PURE__ */ React.createElement(SortableContext, {
45
+ items: props.listItemIds
46
+ }, children)) : /* @__PURE__ */ React.createElement(React.Fragment, null, children)));
47
+ });
48
+ List.displayName = LIST_NAME;
436
49
 
437
- // packages/apps/patterns/react-list/src/components/List/List.tsx
50
+ // packages/ui/primitives/react-list/src/ListItem.tsx
51
+ import { useSortable } from "@dnd-kit/sortable";
52
+ import { CSS } from "@dnd-kit/utilities";
53
+ import * as Collapsible from "@radix-ui/react-collapsible";
54
+ import { useComposedRefs } from "@radix-ui/react-compose-refs";
55
+ import { createContextScope as createContextScope2 } from "@radix-ui/react-context";
56
+ import { Primitive as Primitive2 } from "@radix-ui/react-primitive";
57
+ import { Slot } from "@radix-ui/react-slot";
58
+ import { useControllableState } from "@radix-ui/react-use-controllable-state";
59
+ import React2, { forwardRef as forwardRef2 } from "react";
60
+ import { useId } from "@dxos/react-hooks";
438
61
  function _extends2() {
439
62
  _extends2 = Object.assign || function(target) {
440
63
  for (var i = 1; i < arguments.length; i++) {
@@ -449,78 +72,109 @@ function _extends2() {
449
72
  };
450
73
  return _extends2.apply(this, arguments);
451
74
  }
452
- var ListLoaded = ({ space, list, listItems: propsListItems }) => {
453
- var _a, _b, _c;
454
- const listItems = (_a = useSelection(list == null ? void 0 : list.select().children().filter({
455
- type: LIST_ITEM_TYPE
456
- }))) != null ? _a : propsListItems;
457
- const onAction = useCallback2(async (action) => {
458
- if (isListItemDeletedAction(action)) {
459
- const subject = space.database.getItem(action.deleted.id);
460
- return subject == null ? void 0 : subject.model.set("annotations.deleted", true);
461
- } else if (isListItemCreatedAction(action)) {
462
- } else if (isListItemChangedAction(action)) {
463
- const subject1 = space.database.getItem(action.listItemId);
464
- return Promise.all(Object.keys(action.next).map((prop) => {
465
- return subject1 == null ? void 0 : subject1.model.set(prop, action.next[prop]);
466
- }));
467
- } else {
468
- return Promise.all(Object.keys(action.next).map((prop) => {
469
- return list == null ? void 0 : list.model.set(prop, action.next[prop]);
470
- }));
471
- }
472
- }, [
473
- list,
474
- listItems
475
- ]);
476
- const createListItemId = useCallback2(async () => {
477
- const listItem = await (space == null ? void 0 : space.database.createItem({
478
- model: ObjectModel,
479
- type: LIST_ITEM_TYPE,
480
- parent: list.id
481
- }));
482
- return listItem.id;
483
- }, [
484
- space
485
- ]);
486
- return /* @__PURE__ */ React2.createElement(ListPrimitive, _extends2({}, {
487
- id: list.id,
488
- title: (_b = list.model.get("title")) != null ? _b : "",
489
- description: (_c = list.model.get("description")) != null ? _c : "",
490
- items: (listItems != null ? listItems : []).filter((item) => !item.model.get("annotations.deleted")).reduce((acc, item) => {
491
- acc[item.id] = {
492
- title: item.model.get("title"),
493
- description: item.model.get("description"),
494
- annotations: item.model.get("annotations")
495
- };
496
- return acc;
497
- }, {}),
498
- onChangePeriod: 640,
499
- onAction,
500
- createListItemId
501
- }));
502
- };
503
- var List = ({ spaceKey, itemId }) => {
504
- var _a;
505
- const { t } = useTranslation2("appkit");
506
- const space = useSpace(spaceKey);
507
- const list = ((_a = useSelection(space == null ? void 0 : space.database.select({
508
- id: itemId
509
- }))) != null ? _a : [])[0];
510
- const listItems = useSelection(list == null ? void 0 : list.select().children().filter({
511
- type: LIST_ITEM_TYPE
512
- }));
513
- return space && list && listItems ? /* @__PURE__ */ React2.createElement(ListLoaded, _extends2({}, {
514
- space,
515
- list,
516
- listItems
517
- })) : /* @__PURE__ */ React2.createElement(Loading, {
518
- label: t("generic loading label")
75
+ var LIST_ITEM_NAME = "ListItem";
76
+ var [createListItemContext, createListItemScope] = createContextScope2(LIST_ITEM_NAME, []);
77
+ var [ListItemProvider, useListItemContext] = createListItemContext(LIST_ITEM_NAME);
78
+ var ListItemHeading = /* @__PURE__ */ forwardRef2(({ children, asChild, __listItemScope, ...props }, forwardedRef) => {
79
+ const { headingId } = useListItemContext(LIST_ITEM_NAME, __listItemScope);
80
+ const Root2 = asChild ? Slot : Primitive2.p;
81
+ return /* @__PURE__ */ React2.createElement(Root2, _extends2({}, props, {
82
+ id: headingId,
83
+ ref: forwardedRef
84
+ }), children);
85
+ });
86
+ var ListItemDragHandle = /* @__PURE__ */ forwardRef2(({ __listItemScope, children, ...props }, forwardedRef) => {
87
+ const { draggableAttributes, draggableListeners } = useListItemContext(LIST_ITEM_NAME, __listItemScope);
88
+ return /* @__PURE__ */ React2.createElement("div", _extends2({
89
+ role: "button",
90
+ ref: forwardedRef
91
+ }, props, draggableAttributes, draggableListeners), children);
92
+ });
93
+ var ListItemOpenTrigger = Collapsible.Trigger;
94
+ var ListItemCollapsibleContent = Collapsible.Content;
95
+ var PureListItem = /* @__PURE__ */ forwardRef2((props, forwardedRef) => {
96
+ const { __listScope, __listItemScope, children, selected: propsSelected, defaultSelected, onSelectedChange, open: propsOpen, defaultOpen, onOpenChange, collapsible, id, draggableAttributes, draggableListeners, ...listItemProps } = props;
97
+ const { selectable } = useListContext(LIST_NAME, __listScope);
98
+ const [selected = false, setSelected] = useControllableState({
99
+ prop: propsSelected,
100
+ defaultProp: defaultSelected,
101
+ onChange: onSelectedChange
519
102
  });
520
- };
103
+ const [open = false, setOpen] = useControllableState({
104
+ prop: propsOpen,
105
+ defaultProp: defaultOpen,
106
+ onChange: onOpenChange
107
+ });
108
+ const headingId = useId("listItem__heading");
109
+ const listItem = /* @__PURE__ */ React2.createElement(Primitive2.li, _extends2({}, listItemProps, {
110
+ id,
111
+ ref: forwardedRef,
112
+ "aria-labelledby": headingId
113
+ }, selectable && {
114
+ role: "option",
115
+ "aria-selected": !!selected
116
+ }), children);
117
+ return /* @__PURE__ */ React2.createElement(ListItemProvider, _extends2({
118
+ scope: __listItemScope,
119
+ headingId,
120
+ open,
121
+ selected,
122
+ setSelected
123
+ }, {
124
+ draggableAttributes,
125
+ draggableListeners
126
+ }), collapsible ? /* @__PURE__ */ React2.createElement(Collapsible.Root, {
127
+ asChild: true,
128
+ open,
129
+ onOpenChange: setOpen
130
+ }, listItem) : listItem);
131
+ });
132
+ var DraggableListItem = /* @__PURE__ */ forwardRef2((props, forwardedRef) => {
133
+ const { attributes, listeners, setNodeRef, transform, transition } = useSortable({
134
+ id: props.id
135
+ });
136
+ const ref = useComposedRefs(forwardedRef, setNodeRef);
137
+ return /* @__PURE__ */ React2.createElement(PureListItem, _extends2({}, props, {
138
+ style: {
139
+ ...props.style,
140
+ transform: CSS.Transform.toString(transform),
141
+ transition
142
+ },
143
+ ref
144
+ }, {
145
+ draggableAttributes: attributes,
146
+ draggableListeners: listeners
147
+ }));
148
+ });
149
+ var ListItem = /* @__PURE__ */ forwardRef2((props, forwardedRef) => {
150
+ const { variant } = useListContext(LIST_NAME, props.__listScope);
151
+ const listItemId = useId("listItem", props.id);
152
+ if (variant === "ordered-draggable") {
153
+ return /* @__PURE__ */ React2.createElement(DraggableListItem, _extends2({}, props, {
154
+ ref: forwardedRef,
155
+ id: listItemId
156
+ }));
157
+ } else {
158
+ return /* @__PURE__ */ React2.createElement(PureListItem, _extends2({}, props, {
159
+ ref: forwardedRef,
160
+ id: listItemId
161
+ }));
162
+ }
163
+ });
164
+ ListItem.displayName = LIST_ITEM_NAME;
521
165
  export {
522
- LIST_ITEM_TYPE,
523
- LIST_TYPE,
524
- List
166
+ LIST_ITEM_NAME,
167
+ LIST_NAME,
168
+ List,
169
+ ListItem,
170
+ ListItemCollapsibleContent,
171
+ ListItemDragHandle,
172
+ ListItemHeading,
173
+ ListItemOpenTrigger,
174
+ arrayMove,
175
+ createListItemScope,
176
+ createListScope,
177
+ useListContext,
178
+ useListItemContext
525
179
  };
526
180
  //# sourceMappingURL=index.mjs.map