@valu/block-components 0.3.1 → 0.4.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/README.md +4 -0
- package/dist/components/document-picker/index.cjs +151 -10
- package/dist/components/document-picker/index.cjs.map +1 -1
- package/dist/components/document-picker/index.d.cts +16 -1
- package/dist/components/document-picker/index.d.ts +16 -1
- package/dist/components/document-picker/index.js +152 -11
- package/dist/components/document-picker/index.js.map +1 -1
- package/dist/index.cjs +151 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +152 -11
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -23,6 +23,12 @@ interface DocumentItem {
|
|
|
23
23
|
modified?: string;
|
|
24
24
|
/** Raw REST record so consumer filters can reach beyond the normalized shape. */
|
|
25
25
|
raw?: unknown;
|
|
26
|
+
/**
|
|
27
|
+
* Editor-authored display name that overrides `title` in consumer UIs.
|
|
28
|
+
* Never derived from the REST record — set only by the user via the
|
|
29
|
+
* per-item label field (see `enableItemLabels`).
|
|
30
|
+
*/
|
|
31
|
+
label?: string;
|
|
26
32
|
}
|
|
27
33
|
/** A picked document resolved against the current entity store. */
|
|
28
34
|
interface ResolvedDocumentItem extends DocumentItem {
|
|
@@ -47,6 +53,7 @@ interface DocumentPickerLabels {
|
|
|
47
53
|
missing?: string;
|
|
48
54
|
openLink?: string;
|
|
49
55
|
extensionBadge?: string;
|
|
56
|
+
itemLabel?: string;
|
|
50
57
|
}
|
|
51
58
|
interface RequestContext {
|
|
52
59
|
query: string;
|
|
@@ -100,6 +107,14 @@ interface DocumentPickerProps {
|
|
|
100
107
|
uniqueItems?: boolean;
|
|
101
108
|
/** Show the "Browse Media Library" button. @default true */
|
|
102
109
|
enableMediaLibrary?: boolean;
|
|
110
|
+
/**
|
|
111
|
+
* Make each selected row's display name editable in place: the title is
|
|
112
|
+
* rendered as a text input prefilled with the effective name. Edits are
|
|
113
|
+
* stored on the item as `label` (the attachment itself is untouched);
|
|
114
|
+
* clearing the field — or typing the original title back — removes the
|
|
115
|
+
* override and falls back to the attachment title. @default false
|
|
116
|
+
*/
|
|
117
|
+
enableItemLabels?: boolean;
|
|
103
118
|
/** Show the uppercase extension badge on each row. @default true */
|
|
104
119
|
showExtensionBadge?: boolean;
|
|
105
120
|
/** Show file size on each row. @default true */
|
|
@@ -139,7 +154,7 @@ interface DocumentPickerProps {
|
|
|
139
154
|
* onChange={(items) => setAttributes({ documents: items })}
|
|
140
155
|
* />
|
|
141
156
|
*/
|
|
142
|
-
declare const DocumentPicker: ({ label, hideLabelFromVision, help, variant, value: controlledValue, defaultValue, onChange, maxItems, orderable, placeholder, allowedMimeTypes, allowedExtensions, perPage, inputDelayMs, fetchOnOpen, uniqueItems, enableMediaLibrary, showExtensionBadge, showFileSize, showModifiedDate, filter, request, renderSuggestion, renderSelected, labels, className, id, }: DocumentPickerProps) => react_jsx_runtime.JSX.Element;
|
|
157
|
+
declare const DocumentPicker: ({ label, hideLabelFromVision, help, variant, value: controlledValue, defaultValue, onChange, maxItems, orderable, placeholder, allowedMimeTypes, allowedExtensions, perPage, inputDelayMs, fetchOnOpen, uniqueItems, enableMediaLibrary, enableItemLabels, showExtensionBadge, showFileSize, showModifiedDate, filter, request, renderSuggestion, renderSelected, labels, className, id, }: DocumentPickerProps) => react_jsx_runtime.JSX.Element;
|
|
143
158
|
|
|
144
159
|
interface MediaLibraryButtonProps {
|
|
145
160
|
allowedMimeTypes: string[];
|
|
@@ -23,6 +23,12 @@ interface DocumentItem {
|
|
|
23
23
|
modified?: string;
|
|
24
24
|
/** Raw REST record so consumer filters can reach beyond the normalized shape. */
|
|
25
25
|
raw?: unknown;
|
|
26
|
+
/**
|
|
27
|
+
* Editor-authored display name that overrides `title` in consumer UIs.
|
|
28
|
+
* Never derived from the REST record — set only by the user via the
|
|
29
|
+
* per-item label field (see `enableItemLabels`).
|
|
30
|
+
*/
|
|
31
|
+
label?: string;
|
|
26
32
|
}
|
|
27
33
|
/** A picked document resolved against the current entity store. */
|
|
28
34
|
interface ResolvedDocumentItem extends DocumentItem {
|
|
@@ -47,6 +53,7 @@ interface DocumentPickerLabels {
|
|
|
47
53
|
missing?: string;
|
|
48
54
|
openLink?: string;
|
|
49
55
|
extensionBadge?: string;
|
|
56
|
+
itemLabel?: string;
|
|
50
57
|
}
|
|
51
58
|
interface RequestContext {
|
|
52
59
|
query: string;
|
|
@@ -100,6 +107,14 @@ interface DocumentPickerProps {
|
|
|
100
107
|
uniqueItems?: boolean;
|
|
101
108
|
/** Show the "Browse Media Library" button. @default true */
|
|
102
109
|
enableMediaLibrary?: boolean;
|
|
110
|
+
/**
|
|
111
|
+
* Make each selected row's display name editable in place: the title is
|
|
112
|
+
* rendered as a text input prefilled with the effective name. Edits are
|
|
113
|
+
* stored on the item as `label` (the attachment itself is untouched);
|
|
114
|
+
* clearing the field — or typing the original title back — removes the
|
|
115
|
+
* override and falls back to the attachment title. @default false
|
|
116
|
+
*/
|
|
117
|
+
enableItemLabels?: boolean;
|
|
103
118
|
/** Show the uppercase extension badge on each row. @default true */
|
|
104
119
|
showExtensionBadge?: boolean;
|
|
105
120
|
/** Show file size on each row. @default true */
|
|
@@ -139,7 +154,7 @@ interface DocumentPickerProps {
|
|
|
139
154
|
* onChange={(items) => setAttributes({ documents: items })}
|
|
140
155
|
* />
|
|
141
156
|
*/
|
|
142
|
-
declare const DocumentPicker: ({ label, hideLabelFromVision, help, variant, value: controlledValue, defaultValue, onChange, maxItems, orderable, placeholder, allowedMimeTypes, allowedExtensions, perPage, inputDelayMs, fetchOnOpen, uniqueItems, enableMediaLibrary, showExtensionBadge, showFileSize, showModifiedDate, filter, request, renderSuggestion, renderSelected, labels, className, id, }: DocumentPickerProps) => react_jsx_runtime.JSX.Element;
|
|
157
|
+
declare const DocumentPicker: ({ label, hideLabelFromVision, help, variant, value: controlledValue, defaultValue, onChange, maxItems, orderable, placeholder, allowedMimeTypes, allowedExtensions, perPage, inputDelayMs, fetchOnOpen, uniqueItems, enableMediaLibrary, enableItemLabels, showExtensionBadge, showFileSize, showModifiedDate, filter, request, renderSuggestion, renderSelected, labels, className, id, }: DocumentPickerProps) => react_jsx_runtime.JSX.Element;
|
|
143
158
|
|
|
144
159
|
interface MediaLibraryButtonProps {
|
|
145
160
|
allowedMimeTypes: string[];
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { forwardRef, useId, useState, useCallback, useRef, useMemo, useEffect } from 'react';
|
|
2
2
|
import { QueryClientProvider, QueryClient, useInfiniteQuery, keepPreviousData } from '@tanstack/react-query';
|
|
3
|
-
import { VisuallyHidden, Icon, Button, Popover, Spinner } from '@wordpress/components';
|
|
3
|
+
import { VisuallyHidden, Icon, Button, Popover, Spinner, TextControl } from '@wordpress/components';
|
|
4
4
|
import { __, sprintf, _n } from '@wordpress/i18n';
|
|
5
5
|
import { search, closeSmall, upload, dragHandle, caution, chevronUp, chevronDown } from '@wordpress/icons';
|
|
6
6
|
import styled from '@emotion/styled';
|
|
@@ -550,6 +550,54 @@ var DocMetaInline = styled.div`
|
|
|
550
550
|
white-space: nowrap;
|
|
551
551
|
}
|
|
552
552
|
`;
|
|
553
|
+
var ReorderButtons = styled.span`
|
|
554
|
+
display: none;
|
|
555
|
+
|
|
556
|
+
@container valu-dp-row (min-width: 340px) {
|
|
557
|
+
display: inline-flex;
|
|
558
|
+
}
|
|
559
|
+
`;
|
|
560
|
+
var LabelEditBody = styled.div`
|
|
561
|
+
flex: 1;
|
|
562
|
+
min-width: 0;
|
|
563
|
+
display: flex;
|
|
564
|
+
flex-direction: column;
|
|
565
|
+
gap: 2px;
|
|
566
|
+
padding: 4px 0;
|
|
567
|
+
|
|
568
|
+
.components-base-control,
|
|
569
|
+
.components-text-control__input {
|
|
570
|
+
width: 100%;
|
|
571
|
+
min-width: 0;
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
/* __nextHasNoMarginBottom is not honored by every bundled
|
|
575
|
+
wp-components version — enforce the no-margin layout here. */
|
|
576
|
+
.components-base-control.components-base-control {
|
|
577
|
+
margin-bottom: 0;
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
/* Doubled class beats wp-components' own input rules regardless of
|
|
581
|
+
stylesheet order (the emotion cache may be prepended). */
|
|
582
|
+
.components-text-control__input.components-text-control__input {
|
|
583
|
+
font-size: ${tokens.fontSizeBody};
|
|
584
|
+
height: 28px;
|
|
585
|
+
min-height: 28px;
|
|
586
|
+
padding: 2px 8px;
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
@container valu-dp-row (min-width: ${WIDE_ROW}) {
|
|
590
|
+
flex-direction: row;
|
|
591
|
+
align-items: center;
|
|
592
|
+
gap: ${tokens.spaceMd};
|
|
593
|
+
|
|
594
|
+
.components-base-control {
|
|
595
|
+
flex: 0 1 340px;
|
|
596
|
+
min-width: 180px;
|
|
597
|
+
width: auto;
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
`;
|
|
553
601
|
var Root2 = styled.div`
|
|
554
602
|
color: ${tokens.fg};
|
|
555
603
|
font-size: ${tokens.fontSizeBody};
|
|
@@ -710,6 +758,7 @@ var mapMediaToDocumentItem = (raw) => {
|
|
|
710
758
|
raw
|
|
711
759
|
};
|
|
712
760
|
};
|
|
761
|
+
var displayTitle = (item) => item.label?.trim() || item.title;
|
|
713
762
|
var dedupeAgainst = (items, value, enabled) => {
|
|
714
763
|
if (!enabled || value.length === 0) return items;
|
|
715
764
|
const ids = new Set(value.map((v) => v.id));
|
|
@@ -1714,6 +1763,8 @@ var SelectedItem = ({
|
|
|
1714
1763
|
onRemove,
|
|
1715
1764
|
onMoveUp,
|
|
1716
1765
|
onMoveDown,
|
|
1766
|
+
enableLabelEdit = false,
|
|
1767
|
+
onLabelChange,
|
|
1717
1768
|
render
|
|
1718
1769
|
}) => {
|
|
1719
1770
|
const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({
|
|
@@ -1727,22 +1778,46 @@ var SelectedItem = ({
|
|
|
1727
1778
|
};
|
|
1728
1779
|
const isMissing = item.missing === "deleted";
|
|
1729
1780
|
const missingLabel = labels.missing ?? __("This document is no longer available.", "valu-block-components");
|
|
1781
|
+
const displayName = displayTitle(item);
|
|
1730
1782
|
const removeLabel = labels.remove ? labels.remove : sprintf(
|
|
1731
1783
|
/* translators: %s: document title */
|
|
1732
1784
|
__("Remove %s", "valu-block-components"),
|
|
1733
|
-
|
|
1785
|
+
displayName
|
|
1734
1786
|
);
|
|
1735
1787
|
const moveUpLabel = labels.moveUp ? labels.moveUp : sprintf(
|
|
1736
1788
|
/* translators: %s: document title */
|
|
1737
1789
|
__("Move %s up", "valu-block-components"),
|
|
1738
|
-
|
|
1790
|
+
displayName
|
|
1739
1791
|
);
|
|
1740
1792
|
const moveDownLabel = labels.moveDown ? labels.moveDown : sprintf(
|
|
1741
1793
|
/* translators: %s: document title */
|
|
1742
1794
|
__("Move %s down", "valu-block-components"),
|
|
1743
|
-
|
|
1795
|
+
displayName
|
|
1744
1796
|
);
|
|
1745
1797
|
const modified = showModifiedDate ? formatModified(item.modified) : "";
|
|
1798
|
+
const isLabelEdit = enableLabelEdit && !isMissing && Boolean(onLabelChange);
|
|
1799
|
+
const [labelDraft, setLabelDraft] = useState(null);
|
|
1800
|
+
const commitTimer = useRef(null);
|
|
1801
|
+
useEffect(
|
|
1802
|
+
() => () => {
|
|
1803
|
+
if (commitTimer.current) {
|
|
1804
|
+
clearTimeout(commitTimer.current);
|
|
1805
|
+
}
|
|
1806
|
+
},
|
|
1807
|
+
[]
|
|
1808
|
+
);
|
|
1809
|
+
const normalizeLabel = (value) => {
|
|
1810
|
+
const trimmed = value.trim();
|
|
1811
|
+
return trimmed === "" || trimmed === item.title ? "" : value;
|
|
1812
|
+
};
|
|
1813
|
+
const itemLabelText = labels.itemLabel ?? __("Display name", "valu-block-components");
|
|
1814
|
+
const metaParts = [item.filename];
|
|
1815
|
+
if (showFileSize && item.fileSize) {
|
|
1816
|
+
metaParts.push(formatFileSize(item.fileSize));
|
|
1817
|
+
}
|
|
1818
|
+
if (modified) {
|
|
1819
|
+
metaParts.push(modified);
|
|
1820
|
+
}
|
|
1746
1821
|
return /* @__PURE__ */ jsxs(
|
|
1747
1822
|
SelectedRow2,
|
|
1748
1823
|
{
|
|
@@ -1764,9 +1839,45 @@ var SelectedItem = ({
|
|
|
1764
1839
|
}
|
|
1765
1840
|
) : null,
|
|
1766
1841
|
isMissing ? /* @__PURE__ */ jsx(Icon, { icon: caution, size: 20 }) : showExtensionBadge ? /* @__PURE__ */ jsx(ExtensionBadge, { extension: item.extension }) : null,
|
|
1767
|
-
render ? render(item) : /* @__PURE__ */ jsxs(
|
|
1842
|
+
render ? render(item) : isLabelEdit ? /* @__PURE__ */ jsxs(LabelEditBody, { children: [
|
|
1843
|
+
/* @__PURE__ */ jsx(
|
|
1844
|
+
TextControl,
|
|
1845
|
+
{
|
|
1846
|
+
__nextHasNoMarginBottom: true,
|
|
1847
|
+
__next40pxDefaultSize: false,
|
|
1848
|
+
"aria-label": sprintf(
|
|
1849
|
+
/* translators: 1: display-name field label, 2: filename */
|
|
1850
|
+
"%1$s: %2$s",
|
|
1851
|
+
itemLabelText,
|
|
1852
|
+
item.filename
|
|
1853
|
+
),
|
|
1854
|
+
value: labelDraft ?? item.label ?? item.title,
|
|
1855
|
+
onChange: (value) => {
|
|
1856
|
+
setLabelDraft(value);
|
|
1857
|
+
if (commitTimer.current) {
|
|
1858
|
+
clearTimeout(commitTimer.current);
|
|
1859
|
+
}
|
|
1860
|
+
commitTimer.current = setTimeout(() => {
|
|
1861
|
+
commitTimer.current = null;
|
|
1862
|
+
onLabelChange?.(normalizeLabel(value));
|
|
1863
|
+
}, 300);
|
|
1864
|
+
},
|
|
1865
|
+
onBlur: () => {
|
|
1866
|
+
if (commitTimer.current) {
|
|
1867
|
+
clearTimeout(commitTimer.current);
|
|
1868
|
+
commitTimer.current = null;
|
|
1869
|
+
if (labelDraft !== null) {
|
|
1870
|
+
onLabelChange?.(normalizeLabel(labelDraft));
|
|
1871
|
+
}
|
|
1872
|
+
}
|
|
1873
|
+
setLabelDraft(null);
|
|
1874
|
+
}
|
|
1875
|
+
}
|
|
1876
|
+
),
|
|
1877
|
+
/* @__PURE__ */ jsx(FilenameText, { title: item.filename, children: metaParts.join(" \xB7 ") })
|
|
1878
|
+
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1768
1879
|
/* @__PURE__ */ jsxs(DocRowBody, { children: [
|
|
1769
|
-
/* @__PURE__ */ jsx(PrimaryText, { muted: isMissing, title:
|
|
1880
|
+
/* @__PURE__ */ jsx(PrimaryText, { muted: isMissing, title: displayName, children: isMissing ? missingLabel : displayName }),
|
|
1770
1881
|
!isMissing ? /* @__PURE__ */ jsx(FilenameText, { title: item.filename, children: item.filename }) : null
|
|
1771
1882
|
] }),
|
|
1772
1883
|
!isMissing && (showFileSize || modified) ? /* @__PURE__ */ jsxs(DocMetaInline, { children: [
|
|
@@ -1775,7 +1886,7 @@ var SelectedItem = ({
|
|
|
1775
1886
|
] }) : null
|
|
1776
1887
|
] }),
|
|
1777
1888
|
/* @__PURE__ */ jsxs(ActionColumn, { children: [
|
|
1778
|
-
orderable ? /* @__PURE__ */ jsxs(
|
|
1889
|
+
orderable ? /* @__PURE__ */ jsxs(ReorderButtons, { children: [
|
|
1779
1890
|
/* @__PURE__ */ jsx(
|
|
1780
1891
|
Button,
|
|
1781
1892
|
{
|
|
@@ -1871,7 +1982,8 @@ var SelectedList = ({
|
|
|
1871
1982
|
showHeader = true,
|
|
1872
1983
|
showExtensionBadge,
|
|
1873
1984
|
showFileSize,
|
|
1874
|
-
showModifiedDate
|
|
1985
|
+
showModifiedDate,
|
|
1986
|
+
enableItemLabels = false
|
|
1875
1987
|
}) => {
|
|
1876
1988
|
const resolved = useResolvedDocuments(value);
|
|
1877
1989
|
const [activeKey, setActiveKey] = useState(null);
|
|
@@ -1886,6 +1998,22 @@ var SelectedList = ({
|
|
|
1886
1998
|
(key) => onChange(value.filter((i) => i.key !== key)),
|
|
1887
1999
|
[value, onChange]
|
|
1888
2000
|
);
|
|
2001
|
+
const setLabel = useCallback(
|
|
2002
|
+
(key, label) => onChange(
|
|
2003
|
+
value.map((i) => {
|
|
2004
|
+
if (i.key !== key) {
|
|
2005
|
+
return i;
|
|
2006
|
+
}
|
|
2007
|
+
if (label === "") {
|
|
2008
|
+
const rest = { ...i };
|
|
2009
|
+
delete rest.label;
|
|
2010
|
+
return rest;
|
|
2011
|
+
}
|
|
2012
|
+
return { ...i, label };
|
|
2013
|
+
})
|
|
2014
|
+
),
|
|
2015
|
+
[value, onChange]
|
|
2016
|
+
);
|
|
1889
2017
|
const reorder = useCallback(
|
|
1890
2018
|
(from, to) => {
|
|
1891
2019
|
if (from === to) return;
|
|
@@ -1934,6 +2062,10 @@ var SelectedList = ({
|
|
|
1934
2062
|
onRemove: () => remove(item.key),
|
|
1935
2063
|
...index > 0 ? { onMoveUp: () => reorder(index, index - 1) } : {},
|
|
1936
2064
|
...index < resolved.length - 1 ? { onMoveDown: () => reorder(index, index + 1) } : {},
|
|
2065
|
+
...enableItemLabels ? {
|
|
2066
|
+
enableLabelEdit: true,
|
|
2067
|
+
onLabelChange: (label) => setLabel(item.key, label)
|
|
2068
|
+
} : {},
|
|
1937
2069
|
...renderSelected ? { render: renderSelected } : {}
|
|
1938
2070
|
},
|
|
1939
2071
|
item.key
|
|
@@ -1956,7 +2088,7 @@ var SelectedList = ({
|
|
|
1956
2088
|
onDragCancel: () => setActiveKey(null),
|
|
1957
2089
|
children: [
|
|
1958
2090
|
/* @__PURE__ */ jsx(SortableContext, { items: ids, strategy: verticalListSortingStrategy, children: /* @__PURE__ */ jsx(SelectedListEl, { role: "list", children: rows }) }),
|
|
1959
|
-
/* @__PURE__ */ jsx(DragOverlay, { dropAnimation: defaultDropAnimation, children: activeItem ? /* @__PURE__ */ jsx(DragChip, { title: activeItem
|
|
2091
|
+
/* @__PURE__ */ jsx(DragOverlay, { dropAnimation: defaultDropAnimation, children: activeItem ? /* @__PURE__ */ jsx(DragChip, { title: displayTitle(activeItem) }) : null })
|
|
1960
2092
|
]
|
|
1961
2093
|
}
|
|
1962
2094
|
)
|
|
@@ -1987,6 +2119,7 @@ var DocumentPicker = ({
|
|
|
1987
2119
|
fetchOnOpen = false,
|
|
1988
2120
|
uniqueItems = true,
|
|
1989
2121
|
enableMediaLibrary = true,
|
|
2122
|
+
enableItemLabels = false,
|
|
1990
2123
|
showExtensionBadge = true,
|
|
1991
2124
|
showFileSize = true,
|
|
1992
2125
|
showModifiedDate = false,
|
|
@@ -2078,7 +2211,14 @@ var DocumentPicker = ({
|
|
|
2078
2211
|
...allowedExtensions !== void 0 ? { allowedExtensions } : {},
|
|
2079
2212
|
multiple: false,
|
|
2080
2213
|
value,
|
|
2081
|
-
onSelect: (items) =>
|
|
2214
|
+
onSelect: (items) => {
|
|
2215
|
+
const next = items[items.length - 1];
|
|
2216
|
+
const prev = value[0];
|
|
2217
|
+
const keepLabel = prev?.id === next.id && prev.label !== void 0;
|
|
2218
|
+
handleChange([
|
|
2219
|
+
keepLabel ? { ...next, label: prev.label } : next
|
|
2220
|
+
]);
|
|
2221
|
+
},
|
|
2082
2222
|
labels,
|
|
2083
2223
|
variant: "tertiary",
|
|
2084
2224
|
label: labels.replace
|
|
@@ -2096,7 +2236,8 @@ var DocumentPicker = ({
|
|
|
2096
2236
|
showHeader: value.length > 0,
|
|
2097
2237
|
showExtensionBadge,
|
|
2098
2238
|
showFileSize,
|
|
2099
|
-
showModifiedDate
|
|
2239
|
+
showModifiedDate,
|
|
2240
|
+
enableItemLabels
|
|
2100
2241
|
}
|
|
2101
2242
|
)
|
|
2102
2243
|
] }) }) });
|