@jini-ai/ui 0.5.5 → 0.5.6
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/CHANGELOG.md +4 -0
- package/dist/core/theme/validation.js +40 -38
- package/dist/features/a2ui/renderer.js +15 -13
- package/dist/features/about/react/components/AboutTab.js +64 -34
- package/dist/features/about/rules.d.ts +2 -2
- package/dist/features/about/rules.js +156 -129
- package/dist/features/admin-widgets/components/ImagePreviewModal.d.ts +4 -3
- package/dist/features/admin-widgets/components/ImagePreviewModal.js +6 -10
- package/dist/features/admin-widgets/components/InfoTip.d.ts +3 -2
- package/dist/features/admin-widgets/components/InfoTip.hooks.js +2 -0
- package/dist/features/admin-widgets/components/InfoTip.js +34 -7
- package/dist/features/admin-widgets/components/InfoTip.rules.d.ts +13 -0
- package/dist/features/admin-widgets/components/InfoTip.rules.js +43 -10
- package/dist/features/admin-widgets/components/Lightbox/Lightbox.d.ts +30 -0
- package/dist/features/admin-widgets/components/Lightbox/Lightbox.hooks.d.ts +40 -0
- package/dist/features/admin-widgets/components/Lightbox/Lightbox.hooks.js +128 -0
- package/dist/features/admin-widgets/components/Lightbox/Lightbox.js +18 -0
- package/dist/features/admin-widgets/components/MiddleTruncate.d.ts +14 -0
- package/dist/features/admin-widgets/components/MiddleTruncate.js +12 -0
- package/dist/features/admin-widgets/components/MiddleTruncate.rules.d.ts +20 -0
- package/dist/features/admin-widgets/components/MiddleTruncate.rules.js +21 -0
- package/dist/features/admin-widgets/components/ScrollJump/ScrollJump.d.ts +18 -0
- package/dist/features/admin-widgets/components/ScrollJump/ScrollJump.hooks.d.ts +16 -0
- package/dist/features/admin-widgets/components/ScrollJump/ScrollJump.hooks.js +45 -0
- package/dist/features/admin-widgets/components/ScrollJump/ScrollJump.js +18 -0
- package/dist/features/admin-widgets/components/ScrollJump/ScrollJump.rules.d.ts +32 -0
- package/dist/features/admin-widgets/components/ScrollJump/ScrollJump.rules.js +26 -0
- package/dist/features/admin-widgets/components/SuggestInput/SuggestInput.hooks.js +29 -14
- package/dist/features/admin-widgets/index.d.ts +14 -2
- package/dist/features/admin-widgets/index.js +7 -1
- package/dist/features/admin-widgets/styles/admin-widgets.css +1 -0
- package/dist/features/asset-grid/react/components/AssetCard.js +7 -1
- package/dist/features/asset-grid/react/components/AssetGrid.d.ts +1 -1
- package/dist/features/asset-grid/react/components/AssetGrid.js +38 -18
- package/dist/features/asset-grid/react/components/useAssetGridFilters.d.ts +21 -0
- package/dist/features/asset-grid/react/components/useAssetGridFilters.js +19 -0
- package/dist/features/asset-grid/react/hooks/useAssetGridKeyboardShortcuts.js +16 -11
- package/dist/features/asset-grid/react/hooks/useAssetGridLiveUpdates.d.ts +2 -0
- package/dist/features/asset-grid/react/hooks/useAssetGridLiveUpdates.js +35 -11
- package/dist/features/asset-tree-browser/react/components/AssetTreeBrowser.d.ts +6 -6
- package/dist/features/asset-tree-browser/react/components/AssetTreeBrowser.js +10 -129
- package/dist/features/asset-tree-browser/react/components/AssetTreeBrowserParts.d.ts +50 -0
- package/dist/features/asset-tree-browser/react/components/AssetTreeBrowserParts.js +95 -0
- package/dist/features/asset-tree-browser/react/components/useAssetTreeBrowserController.d.ts +56 -0
- package/dist/features/asset-tree-browser/react/components/useAssetTreeBrowserController.js +80 -0
- package/dist/features/asset-tree-browser/rules.js +40 -22
- package/dist/features/browser-chrome/rules.js +74 -70
- package/dist/features/charts/browser.js +11 -5
- package/dist/features/charts/react.js +2 -2
- package/dist/features/charts/table.js +2 -2
- package/dist/features/command-palette/react/hooks/useCommandPalette.js +3 -9
- package/dist/features/connectors/ConnectorsBrowser.d.ts +4 -4
- package/dist/features/connectors/ConnectorsBrowser.js +26 -14
- package/dist/features/connectors/components/ConnectorCard.js +67 -38
- package/dist/features/connectors/components/ConnectorDetailDrawer.js +62 -31
- package/dist/features/connectors/components/ConnectorGrid.js +11 -6
- package/dist/features/connectors/hooks/useConnectorAuthorization.js +6 -0
- package/dist/features/connectors/hooks/useConnectorCatalog.d.ts +2 -0
- package/dist/features/connectors/hooks/useConnectorCatalog.js +32 -13
- package/dist/features/connectors/hooks/useWiredConnectorsBrowser.d.ts +3 -3
- package/dist/features/connectors/rules.d.ts +8 -1
- package/dist/features/connectors/rules.js +42 -20
- package/dist/features/connectors/types.d.ts +11 -0
- package/dist/features/execution/constants.d.ts +4 -10
- package/dist/features/execution/constants.js +9 -94
- package/dist/features/execution/react/components/ByokProviderForm.d.ts +2 -4
- package/dist/features/execution/react/components/ByokProviderForm.js +140 -43
- package/dist/features/execution/react/components/ExecutionTab.d.ts +1 -2
- package/dist/features/execution/react/components/ExecutionTab.js +52 -30
- package/dist/features/execution/react/components/LocalCliAgentCard.js +12 -3
- package/dist/features/execution/react/components/LocalCliAgentList.js +14 -3
- package/dist/features/execution/react/components/LocalCliAgentSettings.js +14 -3
- package/dist/features/execution/react/hooks/useLocalCliAgentCard.js +54 -36
- package/dist/features/execution/react/hooks/useReasoningControl.js +114 -78
- package/dist/features/execution/rules.d.ts +2 -2
- package/dist/features/execution/rules.js +31 -15
- package/dist/features/execution/types.d.ts +4 -42
- package/dist/features/execution/types.js +0 -17
- package/dist/features/external-mcp/react/components/ExternalMcpTab.d.ts +6 -2
- package/dist/features/external-mcp/react/components/ExternalMcpTab.js +9 -2
- package/dist/features/file-dropzone/react/components/FileDropzone.js +24 -25
- package/dist/features/file-dropzone/react/components/FileDropzoneLightbox.d.ts +2 -2
- package/dist/features/file-dropzone/react/components/FileDropzoneLightbox.js +35 -30
- package/dist/features/file-dropzone/react/components/FileDropzoneThumbnailGrid.js +30 -24
- package/dist/features/file-dropzone/react/components/FileDropzoneZone.d.ts +14 -0
- package/dist/features/file-dropzone/react/components/FileDropzoneZone.js +26 -0
- package/dist/features/html-editor/canvas-content-wrapper.js +13 -13
- package/dist/features/html-editor/canvas-embed-placeholders.js +46 -37
- package/dist/features/html-editor/css.js +76 -69
- package/dist/features/html-editor/editor-blocks.js +47 -33
- package/dist/features/html-editor/editor-serialization.js +6 -5
- package/dist/features/html-editor/protected-elements.js +39 -28
- package/dist/features/html-editor/react/hooks/useInteractiveHtmlEditor.js +4 -4
- package/dist/features/html-editor/source-splice.js +51 -30
- package/dist/features/i18n/dictionaries/settings-dialog.ja.js +1 -0
- package/dist/features/i18n/dictionaries/settings-dialog.zh-CN.js +1 -0
- package/dist/features/i18n/dictionaries/settings-dialog.zh-TW.js +1 -0
- package/dist/features/i18n/locale.js +20 -16
- package/dist/features/iframe-pool/react/dom-sync.js +8 -6
- package/dist/features/integrations/react/components/CodexInstallToggleButton.js +19 -4
- package/dist/features/integrations/react/components/IntegrationsTab.js +60 -14
- package/dist/features/interactive-ui/interactive-ui.css +1 -1
- package/dist/features/interactive-ui/providers/shadcn/data-table.js +10 -7
- package/dist/features/lexical-rich-text-editor/mention-parser.js +60 -57
- package/dist/features/lexical-rich-text-editor/react/hooks/useKeyboardCommands.js +33 -38
- package/dist/features/lexical-rich-text-editor/rules.js +87 -74
- package/dist/features/lexical-rich-text-editor/serialize.js +27 -25
- package/dist/features/mcp-ui/secret-card.js +111 -61
- package/dist/features/mcp-ui/surfaces/confirmation.js +39 -21
- package/dist/features/mcp-ui/surfaces/document.d.ts +1 -1
- package/dist/features/mcp-ui/surfaces/document.js +10 -2
- package/dist/features/mcp-ui/surfaces/fields.js +30 -50
- package/dist/features/mcp-ui/surfaces/form.d.ts +6 -0
- package/dist/features/mcp-ui/surfaces/form.js +43 -21
- package/dist/features/mcp-ui/surfaces/outcome.js +30 -20
- package/dist/features/mcp-ui/surfaces/text-input.js +33 -21
- package/dist/features/mcp-ui/surfaces/tokens.d.ts +6 -1
- package/dist/features/mcp-ui/surfaces/tokens.js +5 -2
- package/dist/features/media-providers/constants.d.ts +1 -0
- package/dist/features/media-providers/constants.js +2 -81
- package/dist/features/media-providers/index.d.ts +1 -1
- package/dist/features/media-providers/ports.d.ts +2 -0
- package/dist/features/media-providers/react/components/MediaProviderCard.d.ts +22 -0
- package/dist/features/media-providers/react/components/MediaProviderCard.js +50 -0
- package/dist/features/media-providers/react/components/MediaProvidersTab.d.ts +5 -6
- package/dist/features/media-providers/react/components/MediaProvidersTab.js +40 -72
- package/dist/features/media-providers/react/components/media-providers-tab-labels.d.ts +11 -0
- package/dist/features/media-providers/react/components/media-providers-tab-labels.js +57 -0
- package/dist/features/media-providers/react/hooks/useMediaProvidersTab.d.ts +4 -2
- package/dist/features/media-providers/react/hooks/useMediaProvidersTab.js +37 -23
- package/dist/features/media-providers/rules.js +17 -10
- package/dist/features/media-providers/types.d.ts +4 -22
- package/dist/features/media-providers/types.js +3 -8
- package/dist/features/memory/formatters.js +127 -92
- package/dist/features/memory/react/components/MemoryConnectedPanel.js +92 -36
- package/dist/features/memory/react/components/MemoryList.js +37 -18
- package/dist/features/memory/react/hooks/useMemoryExtractions.store.js +42 -36
- package/dist/features/notifications/react/components/NotificationsTab.js +28 -28
- package/dist/features/observability/long-task.d.ts +0 -12
- package/dist/features/observability/long-task.js +15 -19
- package/dist/features/observability/resource-error.d.ts +0 -10
- package/dist/features/observability/resource-error.js +18 -13
- package/dist/features/observability/stuck-run.js +10 -6
- package/dist/features/observability/telemetry-url.d.ts +6 -0
- package/dist/features/observability/telemetry-url.js +16 -0
- package/dist/features/observability/white-screen.js +12 -24
- package/dist/features/panel-kit/fetch-query/adapter.react.d.ts +2 -2
- package/dist/features/panel-kit/fetch-query/adapter.react.js +4 -2
- package/dist/features/panel-kit/fetch-query/adapter.tanstack.js +46 -33
- package/dist/features/panel-kit/helpers/standing-draft-local-backup.js +3 -1
- package/dist/features/panel-kit/hooks/use-settings-slice.hooks.js +3 -1
- package/dist/features/privacy/react/components/PrivacyTab.js +24 -13
- package/dist/features/progress-card/components/ProgressCard.js +7 -3
- package/dist/features/progress-card/reference-adapters.js +59 -54
- package/dist/features/project-locations/react/components/ProjectLocationsTab.js +24 -15
- package/dist/features/project-locations/react/hooks/useProjectLocationsTab.d.ts +8 -0
- package/dist/features/project-locations/react/hooks/useProjectLocationsTab.js +31 -23
- package/dist/features/resource-dashboard/react/components/ResourceBoard.js +6 -47
- package/dist/features/resource-dashboard/react/components/ResourceBoardView.d.ts +2 -2
- package/dist/features/resource-dashboard/react/components/ResourceBoardView.js +3 -6
- package/dist/features/resource-dashboard/react/components/ResourceBoardViewParts.d.ts +15 -0
- package/dist/features/resource-dashboard/react/components/ResourceBoardViewParts.js +35 -0
- package/dist/features/resource-dashboard/react/components/ResourceCard.js +5 -16
- package/dist/features/resource-dashboard/react/components/ResourceCardParts.d.ts +34 -0
- package/dist/features/resource-dashboard/react/components/ResourceCardParts.js +34 -0
- package/dist/features/resource-dashboard/react/components/ResourceRowList.js +3 -1
- package/dist/features/resource-dashboard/react/components/ResourceRowListItem.js +2 -2
- package/dist/features/resource-dashboard/react/components/ResourceRowListItemParts.d.ts +19 -0
- package/dist/features/resource-dashboard/react/components/ResourceRowListItemParts.js +11 -0
- package/dist/features/resource-dashboard/react/components/ResourceRowListView.d.ts +1 -1
- package/dist/features/resource-dashboard/react/components/ResourceRowListView.js +4 -4
- package/dist/features/resource-dashboard/react/components/ResourceRowListViewParts.d.ts +10 -0
- package/dist/features/resource-dashboard/react/components/ResourceRowListViewParts.js +20 -0
- package/dist/features/resource-dashboard/react/components/resourceBoardProps.d.ts +48 -0
- package/dist/features/resource-dashboard/react/components/resourceBoardProps.js +70 -0
- package/dist/features/resource-dashboard/react/components/resourceRowListProps.d.ts +19 -0
- package/dist/features/resource-dashboard/react/components/resourceRowListProps.js +14 -0
- package/dist/features/resource-dashboard/react/components/translatedErrorLabelProps.d.ts +16 -0
- package/dist/features/resource-dashboard/react/components/translatedErrorLabelProps.js +13 -0
- package/dist/features/resource-dashboard/rules.js +2 -8
- package/dist/features/sketch-editor/dom.js +150 -99
- package/dist/features/sketch-editor/react/components/SketchEditor.js +26 -15
- package/dist/features/skills/react/components/SkillDraftForm.js +13 -19
- package/dist/features/skills/react/components/SkillDraftForm.labels.d.ts +31 -0
- package/dist/features/skills/react/components/SkillDraftForm.labels.js +54 -0
- package/dist/features/skills/react/components/SkillRow.js +38 -18
- package/dist/features/skills/react/components/SkillRow.labels.d.ts +7 -0
- package/dist/features/skills/react/components/SkillRow.labels.js +18 -0
- package/dist/features/skills/react/components/SkillsTab.js +24 -14
- package/dist/features/skills/react/components/SkillsTab.labels.d.ts +7 -0
- package/dist/features/skills/react/components/SkillsTab.labels.js +11 -0
- package/dist/features/skills/rules.js +32 -23
- package/dist/features/source-config-list/agent-handles.js +2 -1
- package/dist/features/source-config-list/dependencies.js +53 -49
- package/dist/features/source-config-list/index.d.ts +3 -3
- package/dist/features/source-config-list/react/components/SourceConfigAddForm.d.ts +6 -5
- package/dist/features/source-config-list/react/components/SourceConfigAddForm.js +38 -7
- package/dist/features/source-config-list/react/components/SourceConfigField.js +69 -25
- package/dist/features/source-config-list/react/components/SourceConfigItemCard.d.ts +6 -5
- package/dist/features/source-config-list/react/components/SourceConfigItemCard.js +76 -20
- package/dist/features/source-config-list/react/components/SourceConfigListView.d.ts +5 -3
- package/dist/features/source-config-list/react/components/SourceConfigListView.js +33 -3
- package/dist/features/source-config-list/react/components/SourceConfigTestControl.js +17 -1
- package/dist/features/source-config-list/react/components/SourceConfigTrustOptions.d.ts +11 -0
- package/dist/features/source-config-list/react/components/SourceConfigTrustOptions.js +12 -0
- package/dist/features/source-config-list/types.d.ts +14 -0
- package/dist/features/tab-launcher-menu/react/components/TabLauncherMenu.js +25 -1
- package/dist/features/tab-launcher-menu/react/hooks/useTabLauncherMenu.js +15 -16
- package/dist/features/tab-strip/react/components/TabBar.js +8 -1
- package/dist/features/tabbed-dialog/react/components/TabbedDialog.js +8 -30
- package/dist/features/tabbed-dialog/react/components/TabbedDialogChrome.d.ts +15 -0
- package/dist/features/tabbed-dialog/react/components/TabbedDialogChrome.js +8 -0
- package/dist/features/tabbed-dialog/react/components/TabbedDialogHeader.d.ts +12 -0
- package/dist/features/tabbed-dialog/react/components/TabbedDialogHeader.js +6 -0
- package/dist/features/tabbed-dialog/react/components/TabbedDialogSidebar.d.ts +27 -0
- package/dist/features/tabbed-dialog/react/components/TabbedDialogSidebar.js +12 -0
- package/dist/features/tabbed-dialog/react/components/tabbedDialogView.d.ts +43 -0
- package/dist/features/tabbed-dialog/react/components/tabbedDialogView.js +59 -0
- package/dist/features/version-manager/dependencies.d.ts +3 -1
- package/dist/features/version-manager/dependencies.js +3 -2
- package/dist/features/version-manager/react/components/VersionManagerModal.js +10 -6
- package/dist/features/version-manager/react/hooks/useVersionManager.js +7 -4
- package/dist/features/viewer-shell/react/components/CommentSidePanel.js +103 -50
- package/dist/features/viewer-shell/react/components/MarkdownSplitPane.js +28 -8
- package/dist/features/viewer-shell/react/hooks/useCommentReorder.js +22 -16
- package/dist/features/viewer-shell/rules.js +19 -23
- package/dist/react/components/CustomSelect.d.ts +38 -1
- package/dist/react/components/CustomSelect.js +94 -38
- package/dist/react/components/OnboardingDropdown.js +20 -8
- package/dist/react/components/RemixIcon.stylesheet.js +3 -1
- package/dist/react/components/Toast.js +13 -2
- package/dist/react/components/TooltipLayer.js +5 -14
- package/dist/react/components/WorkingDirPicker.js +78 -50
- package/dist/react/components/remixicon-font-recovery.js +38 -30
- package/dist/react/components/select-popover.d.ts +8 -6
- package/dist/react/components/select-popover.js +33 -29
- package/dist/react/mcp-ui/McpUiHost.d.ts +1 -1
- package/dist/react/mcp-ui/McpUiHost.js +10 -11
- package/dist/react/mcp-ui/host-message-source.d.ts +14 -2
- package/dist/react/mcp-ui/host-message-source.js +15 -5
- package/dist/react/mcp-ui/mcp-ui-host-frame.d.ts +41 -0
- package/dist/react/mcp-ui/mcp-ui-host-frame.js +39 -0
- package/dist/renderers/annotation-canvas/react/components/AnnotationCanvas.js +97 -69
- package/dist/renderers/preview-modal-shell/react/components/PreviewModalShell.js +59 -30
- package/dist/renderers/react/components/ArtifactView.js +9 -6
- package/dist/renderers/srcdoc/build.d.ts +4 -1
- package/dist/renderers/srcdoc/build.js +62 -48
- package/dist/styles/admin.css +29 -14
- package/dist/styles/lightbox.css +142 -0
- package/dist/styles/variables.css +128 -0
- package/dist/theme/apply.js +9 -5
- package/dist/utils/auto-open-file.d.ts +2 -1
- package/dist/utils/auto-open-file.js +69 -85
- package/dist/utils/markdown-scroll-sync.js +108 -87
- package/dist/utils/polygon-selection.js +25 -26
- package/dist/utils/smooth-scroll-to-top.d.ts +1 -1
- package/dist/utils/smooth-scroll-to-top.js +2 -32
- package/dist/utils/sse.js +26 -26
- package/dist/utils/unit-bezier.d.ts +7 -0
- package/dist/utils/unit-bezier.js +38 -0
- package/package.json +7 -10
- package/dist/features/admin-widgets/components/ImagePreviewModal.hooks.d.ts +0 -13
- package/dist/features/admin-widgets/components/ImagePreviewModal.hooks.js +0 -46
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { useState } from 'react';
|
|
3
|
-
import { Icon } from '../../../../react/components/Icon.js';
|
|
4
3
|
import { useGlobalKeydown } from '../../../../browser/useGlobalKeydown.js';
|
|
5
4
|
import { useT } from '../../../i18n/index.js';
|
|
6
5
|
import { useFileDropzone } from '../hooks/useFileDropzone.js';
|
|
@@ -8,6 +7,7 @@ import { useFileDropzonePreviews } from '../hooks/useFileDropzonePreviews.js';
|
|
|
8
7
|
import { FileDropzoneThumbnailGrid } from './FileDropzoneThumbnailGrid.js';
|
|
9
8
|
import { FileDropzoneLightbox } from './FileDropzoneLightbox.js';
|
|
10
9
|
import { FileDropzoneNameList } from './FileDropzoneNameList.js';
|
|
10
|
+
import { FileDropzoneZone } from './FileDropzoneZone.js';
|
|
11
11
|
// Stable identity for the "no files" case — `files ?? []` would otherwise
|
|
12
12
|
// allocate a fresh array every render, and `useFileDropzonePreviews` keys its
|
|
13
13
|
// effects on `files` by reference: a fresh array every render re-triggers
|
|
@@ -25,7 +25,7 @@ const NO_FILES = [];
|
|
|
25
25
|
* drag/drop + click-to-browse resolving to a flat `File[]` — configured
|
|
26
26
|
* differently; see `packages/ui/source-map.md` for the full writeup.
|
|
27
27
|
*/
|
|
28
|
-
export function FileDropzone({ label, prompt, helper, accept, directory
|
|
28
|
+
export function FileDropzone({ label, prompt, helper, accept, directory, enablePaste = false, files, onRemove, names, onRemoveName, onFiles, onZoneClick, onError, onProcessingStart, onBrowseFolder, secondaryAction, useFileDropzone: useFileDropzoneHook = useFileDropzone, useFileDropzonePreviews: useFileDropzonePreviewsHook = useFileDropzonePreviews, }) {
|
|
29
29
|
const t = useT();
|
|
30
30
|
const [lightboxFile, setLightboxFile] = useState(null);
|
|
31
31
|
const dropzone = useFileDropzoneHook({ onFiles, onZoneClick, onError, onProcessingStart, enablePaste });
|
|
@@ -36,28 +36,27 @@ export function FileDropzone({ label, prompt, helper, accept, directory = false,
|
|
|
36
36
|
setLightboxFile(null);
|
|
37
37
|
},
|
|
38
38
|
}, { enabled: lightboxFile !== null });
|
|
39
|
-
function onZoneKeyDown(event) {
|
|
40
|
-
if (event.key === 'Enter' || event.key === ' ') {
|
|
41
|
-
event.preventDefault();
|
|
42
|
-
dropzone.openPicker();
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
const defaultPrompt = enablePaste ? t('Drag & drop, paste, or browse') : t('Drag & drop or browse');
|
|
46
|
-
const promptText = prompt ? t(prompt) : defaultPrompt;
|
|
47
39
|
const isSimpleVariant = names !== undefined;
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
const
|
|
51
|
-
return (_jsxs("div", { className: "jini-file-dropzone", children: [label ? _jsx("strong", { className: "jini-file-dropzone__label", children: t(label) }) : null, _jsxs("div", { className: "jini-file-dropzone__wrap", children: [
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
40
|
+
// The helper renders inside the zone for the thumbnail-grid variant, and as a
|
|
41
|
+
// paragraph under the staged names for the simple (`names`) variant.
|
|
42
|
+
const helperText = helper ? t(helper) : undefined;
|
|
43
|
+
return (_jsxs("div", { className: "jini-file-dropzone", children: [label ? _jsx("strong", { className: "jini-file-dropzone__label", children: t(label) }) : null, _jsxs("div", { className: "jini-file-dropzone__wrap", children: [_jsx(FileDropzoneZone, { dropzone: dropzone, zoneText: resolveZoneText({ t, enablePaste, names }, { prompt, onRemoveName }), accept: accept, directory: directory, enablePaste: enablePaste, hint: isSimpleVariant ? undefined : helperText }), onBrowseFolder ? (_jsx("button", { type: "button", className: "jini-file-dropzone__browse-folder", onClick: onBrowseFolder, children: t('Browse folder') })) : null] }), _jsx(FileDropzoneStaged, { previews: previews, lightboxFile: lightboxFile, setLightboxFile: setLightboxFile, secondaryAction: secondaryAction, label: label, names: names, onRemoveName: onRemoveName, files: files, onRemove: onRemove, simpleHelper: isSimpleVariant ? helperText : undefined })] }));
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* The zone's inner text: the staged names themselves for the simple variant
|
|
47
|
+
* when they can't be removed individually (no `onRemoveName` → no chip list),
|
|
48
|
+
* otherwise the host prompt or a default drag/drop(/paste)/browse prompt.
|
|
49
|
+
*/
|
|
50
|
+
function resolveZoneText({ t, enablePaste, names }, { prompt, onRemoveName }) {
|
|
51
|
+
if (names && names.length > 0 && !onRemoveName)
|
|
52
|
+
return names.join(', ');
|
|
53
|
+
if (prompt)
|
|
54
|
+
return t(prompt);
|
|
55
|
+
return enablePaste ? t('Drag & drop, paste, or browse') : t('Drag & drop or browse');
|
|
56
|
+
}
|
|
57
|
+
/** Everything below the zone: the secondary action, the staged names/thumbnails, the simple-variant helper, and the lightbox. Empty `names`/`files` render nothing — `FileDropzoneNameList` and `FileDropzoneThumbnailGrid` both return `null` for an empty list. */
|
|
58
|
+
function FileDropzoneStaged({ previews, lightboxFile, setLightboxFile, secondaryAction, label, names, onRemoveName, files, onRemove, simpleHelper, }) {
|
|
59
|
+
const t = useT();
|
|
60
|
+
return (_jsxs(_Fragment, { children: [secondaryAction ? (_jsx("div", { className: "jini-file-dropzone__secondary", children: _jsx("button", { type: "button", className: "jini-file-dropzone__secondary-action", onClick: secondaryAction.onClick, children: t(secondaryAction.label) }) })) : null, names && onRemoveName ? (_jsx(FileDropzoneNameList, { names: names, onRemoveName: onRemoveName, ariaLabel: label ? t('{label} selections', { label: t(label) }) : t('Selections') })) : null, files ? (_jsx(FileDropzoneThumbnailGrid, { files: files, previews: previews, onSelect: setLightboxFile, onRemove: onRemove })) : null, simpleHelper ? _jsx("p", { className: "jini-file-dropzone__helper", children: simpleHelper }) : null, lightboxFile ? (_jsx(FileDropzoneLightbox, { file: lightboxFile, previews: previews, onClose: () => setLightboxFile(null) })) : null] }));
|
|
62
61
|
}
|
|
63
62
|
//# sourceMappingURL=FileDropzone.js.map
|
|
@@ -4,6 +4,6 @@ export interface FileDropzoneLightboxProps {
|
|
|
4
4
|
previews: FileDropzonePreviewState;
|
|
5
5
|
onClose: () => void;
|
|
6
6
|
}
|
|
7
|
-
/** Click-to-enlarge, kind-aware preview for one staged file — image, PDF embed, HTML mini-render, video/audio player, font specimen, or a text snippet, with a name/size fallback card for everything else.
|
|
8
|
-
export declare function FileDropzoneLightbox({ file, previews, onClose }: FileDropzoneLightboxProps): import("react").
|
|
7
|
+
/** Click-to-enlarge, kind-aware preview for one staged file — image, PDF embed, HTML mini-render, video/audio player, font specimen, or a text snippet, with a name/size fallback card for everything else. Rendered in the shared `Lightbox` (a top-layer native dialog, so no portal is needed). Ported from `DesignSystemAssetDropzone.tsx`'s lightbox. */
|
|
8
|
+
export declare function FileDropzoneLightbox({ file, previews, onClose }: FileDropzoneLightboxProps): import("react").JSX.Element;
|
|
9
9
|
//# sourceMappingURL=FileDropzoneLightbox.d.ts.map
|
|
@@ -1,44 +1,49 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { createPortal } from 'react-dom';
|
|
3
2
|
import { Icon } from '../../../../react/components/Icon.js';
|
|
3
|
+
import { Lightbox } from '../../../admin-widgets/components/Lightbox/Lightbox.js';
|
|
4
4
|
import { useT } from '../../../i18n/index.js';
|
|
5
5
|
import { FILE_DROPZONE_FONT_PANGRAM, FILE_DROPZONE_FONT_SPECIMEN, FILE_DROPZONE_GLYPH_ICON } from '../../constants.js';
|
|
6
6
|
import { fileDropzoneExtensionLabel, fileDropzoneKind, fileDropzoneSizeLabel } from '../../rules.js';
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
}
|
|
24
|
-
|
|
7
|
+
/** Renders `render(url)` once the file's object URL has resolved, `null` (→ fallback card) until then. */
|
|
8
|
+
function withUrl(render) {
|
|
9
|
+
return ({ file, previews }) => {
|
|
10
|
+
const url = previews.previewUrls.get(file);
|
|
11
|
+
return url ? render(url, file) : null;
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Per-kind stage renderers. Each returns `null` while its preview source is
|
|
16
|
+
* not available yet (no object URL, no loaded font family, no text snippet),
|
|
17
|
+
* so `renderStage` shows the name/size fallback card. Kinds with no entry
|
|
18
|
+
* (slides/other) always render the fallback card.
|
|
19
|
+
*/
|
|
20
|
+
const STAGE_RENDERERS = {
|
|
21
|
+
image: withUrl((url, file) => _jsx("img", { src: url, alt: file.name, className: "jini-file-dropzone__lightbox-img" })),
|
|
22
|
+
video: withUrl((url) => _jsx("video", { src: url, className: "jini-file-dropzone__lightbox-video", controls: true, autoPlay: true, playsInline: true })),
|
|
23
|
+
audio: withUrl((url) => (_jsxs("div", { className: "jini-file-dropzone__lightbox-audio", children: [_jsx("span", { className: "jini-file-dropzone__lightbox-audio-icon", children: _jsx(Icon, { name: "volume", size: 34 }) }), _jsx("audio", { src: url, controls: true, className: "jini-file-dropzone__lightbox-audio-player" })] }))),
|
|
24
|
+
pdf: withUrl((url, file) => _jsx("iframe", { src: url, className: "jini-file-dropzone__lightbox-frame", title: file.name })),
|
|
25
|
+
html: withUrl((url, file) => (_jsx("iframe", { src: url, className: "jini-file-dropzone__lightbox-frame", title: file.name, sandbox: "allow-scripts allow-popups" }))),
|
|
26
|
+
font: ({ file, previews }) => {
|
|
25
27
|
const family = previews.fontFamilies.get(file);
|
|
26
|
-
if (family)
|
|
27
|
-
return
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
28
|
+
if (!family)
|
|
29
|
+
return null;
|
|
30
|
+
return (_jsxs("div", { className: "jini-file-dropzone__lightbox-font", style: { fontFamily: `'${family}'` }, children: [_jsxs("div", { className: "jini-file-dropzone__lightbox-font-hero", children: [FILE_DROPZONE_FONT_SPECIMEN, "Bb Cc"] }), _jsx("div", { className: "jini-file-dropzone__lightbox-font-pangram", children: FILE_DROPZONE_FONT_PANGRAM }), _jsxs("div", { className: "jini-file-dropzone__lightbox-font-scale", children: [_jsx("span", { style: { fontSize: 13 }, children: FILE_DROPZONE_FONT_PANGRAM }), _jsx("span", { style: { fontSize: 18 }, children: FILE_DROPZONE_FONT_PANGRAM }), _jsx("span", { style: { fontSize: 26 }, children: FILE_DROPZONE_FONT_PANGRAM })] })] }));
|
|
31
|
+
},
|
|
32
|
+
text: ({ t, file, previews }) => {
|
|
31
33
|
const snippet = previews.textSnippets.get(file);
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
34
|
+
return snippet != null ? _jsx("pre", { className: "jini-file-dropzone__lightbox-text", children: snippet || t('(empty file)') }) : null;
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
function renderFallback({ t, file, kind }) {
|
|
36
38
|
return (_jsxs("div", { className: "jini-file-dropzone__lightbox-fallback", children: [_jsx("span", { className: "jini-file-dropzone__lightbox-fallback-glyph", "data-kind": kind, children: _jsx(Icon, { name: FILE_DROPZONE_GLYPH_ICON[kind], size: 40 }) }), _jsx("p", { className: "jini-file-dropzone__lightbox-fallback-name", children: file.name }), _jsxs("p", { className: "jini-file-dropzone__lightbox-fallback-meta", children: [fileDropzoneExtensionLabel(file), " \u00B7 ", fileDropzoneSizeLabel(file.size) || '—'] }), _jsx("p", { className: "jini-file-dropzone__lightbox-fallback-hint", children: t('No inline preview for this file type.') })] }));
|
|
37
39
|
}
|
|
38
|
-
|
|
40
|
+
function renderStage({ t, file, kind, previews }) {
|
|
41
|
+
return STAGE_RENDERERS[kind]?.({ t, file, previews }) ?? renderFallback({ t, file, kind });
|
|
42
|
+
}
|
|
43
|
+
/** Click-to-enlarge, kind-aware preview for one staged file — image, PDF embed, HTML mini-render, video/audio player, font specimen, or a text snippet, with a name/size fallback card for everything else. Rendered in the shared `Lightbox` (a top-layer native dialog, so no portal is needed). Ported from `DesignSystemAssetDropzone.tsx`'s lightbox. */
|
|
39
44
|
export function FileDropzoneLightbox({ file, previews, onClose }) {
|
|
40
45
|
const t = useT();
|
|
41
46
|
const kind = fileDropzoneKind(file);
|
|
42
|
-
return
|
|
47
|
+
return (_jsx(Lightbox, { open: true, title: file.name, onClose: onClose, className: "jini-file-dropzone__lightbox", labels: { close: t('Close preview') }, actions: _jsx("span", { className: "jini-file-dropzone__lightbox-meta", children: fileDropzoneSizeLabel(file.size) }), children: _jsx("div", { className: "jini-file-dropzone__lightbox-stage", "data-kind": kind, children: renderStage({ t, file, kind, previews }) }) }));
|
|
43
48
|
}
|
|
44
49
|
//# sourceMappingURL=FileDropzoneLightbox.js.map
|
|
@@ -3,33 +3,39 @@ import { Icon } from '../../../../react/components/Icon.js';
|
|
|
3
3
|
import { useT } from '../../../i18n/index.js';
|
|
4
4
|
import { FILE_DROPZONE_FONT_SPECIMEN, FILE_DROPZONE_GLYPH_ICON, FILE_DROPZONE_TEXT_THUMB_CHARS } from '../../constants.js';
|
|
5
5
|
import { fileDropzoneExtensionLabel, fileDropzoneKind, fileDropzoneStagingKey } from '../../rules.js';
|
|
6
|
-
function renderGlyph(file, kind) {
|
|
6
|
+
function renderGlyph({ file, kind }) {
|
|
7
7
|
return (_jsxs("span", { className: "jini-file-dropzone__glyph", "data-kind": kind, children: [_jsx(Icon, { name: FILE_DROPZONE_GLYPH_ICON[kind], size: 20 }), _jsx("span", { className: "jini-file-dropzone__glyph-ext", children: fileDropzoneExtensionLabel(file) })] }));
|
|
8
8
|
}
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
}
|
|
17
|
-
|
|
9
|
+
/**
|
|
10
|
+
* Per-kind thumbnail renderers. Each returns `null` while its preview source
|
|
11
|
+
* (object URL, loaded font family, non-blank text snippet) is not available
|
|
12
|
+
* yet, so `renderThumb` falls back to the extension glyph. Kinds with no entry
|
|
13
|
+
* (pdf/audio/slides/other) always render the glyph.
|
|
14
|
+
*/
|
|
15
|
+
const THUMB_RENDERERS = {
|
|
16
|
+
image: ({ file, previews }) => {
|
|
17
|
+
const url = previews.previewUrls.get(file);
|
|
18
|
+
return url ? _jsx("img", { src: url, alt: "", className: "jini-file-dropzone__thumb", loading: "lazy" }) : null;
|
|
19
|
+
},
|
|
20
|
+
video: ({ file, previews }) => {
|
|
21
|
+
const url = previews.previewUrls.get(file);
|
|
22
|
+
return url ? (_jsx("video", { className: "jini-file-dropzone__thumb", src: url, muted: true, playsInline: true, preload: "metadata", tabIndex: -1 })) : null;
|
|
23
|
+
},
|
|
24
|
+
font: ({ file, previews }) => {
|
|
18
25
|
const family = previews.fontFamilies.get(file);
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
}
|
|
26
|
-
if (kind === 'text') {
|
|
26
|
+
return family ? (_jsx("span", { className: "jini-file-dropzone__font-thumb", style: { fontFamily: `'${family}'` }, "aria-hidden": true, children: FILE_DROPZONE_FONT_SPECIMEN })) : null;
|
|
27
|
+
},
|
|
28
|
+
html: ({ file, previews }) => {
|
|
29
|
+
const url = previews.previewUrls.get(file);
|
|
30
|
+
return url ? (_jsx("span", { className: "jini-file-dropzone__frame-thumb", "aria-hidden": true, children: _jsx("iframe", { className: "jini-file-dropzone__html-thumb", src: url, title: "", sandbox: "", tabIndex: -1 }) })) : null;
|
|
31
|
+
},
|
|
32
|
+
text: ({ file, previews }) => {
|
|
27
33
|
const snippet = previews.textSnippets.get(file);
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
return renderGlyph(file, kind);
|
|
34
|
+
return snippet?.trim() ? (_jsx("span", { className: "jini-file-dropzone__text-thumb", "aria-hidden": true, children: snippet.slice(0, FILE_DROPZONE_TEXT_THUMB_CHARS) })) : null;
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
function renderThumb({ file, kind, previews }) {
|
|
38
|
+
return THUMB_RENDERERS[kind]?.({ file, previews }) ?? renderGlyph({ file, kind });
|
|
33
39
|
}
|
|
34
40
|
/** Kind-aware thumbnail grid over staged files, with remove tiles and click-to-select (the host renders the lightbox — see `FileDropzoneLightbox`). Ported from `DesignSystemAssetDropzone.tsx`'s staged-asset grid. */
|
|
35
41
|
export function FileDropzoneThumbnailGrid({ files, previews, onSelect, onRemove }) {
|
|
@@ -38,7 +44,7 @@ export function FileDropzoneThumbnailGrid({ files, previews, onSelect, onRemove
|
|
|
38
44
|
return null;
|
|
39
45
|
return (_jsx("ul", { className: "jini-file-dropzone__grid", "aria-label": t('Staged files'), children: files.map((file) => {
|
|
40
46
|
const kind = fileDropzoneKind(file);
|
|
41
|
-
return (_jsxs("li", { className: "jini-file-dropzone__tile", children: [_jsx("button", { type: "button", className: "jini-file-dropzone__tile-main", onClick: () => onSelect(file), title: file.name, children: renderThumb(file, kind, previews) }), onRemove ? (_jsx("button", { type: "button", className: "jini-file-dropzone__remove", "aria-label": t('Remove {name}', { name: file.name }), onClick: () => onRemove(file), children: _jsx(Icon, { name: "close", size: 12 }) })) : null, _jsx("span", { className: "jini-file-dropzone__caption", title: file.name, children: file.name })] }, fileDropzoneStagingKey(file)));
|
|
47
|
+
return (_jsxs("li", { className: "jini-file-dropzone__tile", children: [_jsx("button", { type: "button", className: "jini-file-dropzone__tile-main", onClick: () => onSelect(file), title: file.name, children: renderThumb({ file, kind, previews }) }), onRemove ? (_jsx("button", { type: "button", className: "jini-file-dropzone__remove", "aria-label": t('Remove {name}', { name: file.name }), onClick: () => onRemove(file), children: _jsx(Icon, { name: "close", size: 12 }) })) : null, _jsx("span", { className: "jini-file-dropzone__caption", title: file.name, children: file.name })] }, fileDropzoneStagingKey(file)));
|
|
42
48
|
}) }));
|
|
43
49
|
}
|
|
44
50
|
//# sourceMappingURL=FileDropzoneThumbnailGrid.js.map
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { UseFileDropzoneResult } from '../hooks/useFileDropzone.js';
|
|
2
|
+
export interface FileDropzoneZoneProps {
|
|
3
|
+
dropzone: UseFileDropzoneResult;
|
|
4
|
+
/** Text shown inside the zone (the prompt, or the staged names for the simple variant without remove chips). */
|
|
5
|
+
zoneText: string;
|
|
6
|
+
accept?: string | undefined;
|
|
7
|
+
directory?: boolean | undefined;
|
|
8
|
+
enablePaste?: boolean | undefined;
|
|
9
|
+
/** Already-translated hint shown inside the zone under the prompt. */
|
|
10
|
+
hint?: string | undefined;
|
|
11
|
+
}
|
|
12
|
+
/** The keyboard-activatable drag/drop/click zone of `FileDropzone`, with its nested native file input. Internal to the file-dropzone feature. */
|
|
13
|
+
export declare function FileDropzoneZone({ dropzone, zoneText, accept, directory, enablePaste, hint }: FileDropzoneZoneProps): import("react").JSX.Element;
|
|
14
|
+
//# sourceMappingURL=FileDropzoneZone.d.ts.map
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Icon } from '../../../../react/components/Icon.js';
|
|
3
|
+
import { useT } from '../../../i18n/index.js';
|
|
4
|
+
/** The keyboard-activatable drag/drop/click zone of `FileDropzone`, with its nested native file input. Internal to the file-dropzone feature. */
|
|
5
|
+
export function FileDropzoneZone({ dropzone, zoneText, accept, directory, enablePaste, hint }) {
|
|
6
|
+
const t = useT();
|
|
7
|
+
function onZoneKeyDown(event) {
|
|
8
|
+
if (event.key === 'Enter' || event.key === ' ') {
|
|
9
|
+
event.preventDefault();
|
|
10
|
+
dropzone.openPicker();
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
const directoryInputProps = directory ? { webkitdirectory: '', directory: '' } : {};
|
|
14
|
+
return (_jsxs("div", { className: `jini-file-dropzone__zone${dropzone.dragOver ? ' is-drag-over' : ''}`, role: "button", tabIndex: 0, "aria-label": t('Add files — drag and drop{paste}, or click to browse', {
|
|
15
|
+
paste: enablePaste ? t(', paste') : '',
|
|
16
|
+
}), "data-testid": "file-dropzone-zone", onClick: dropzone.openPicker, onKeyDown: onZoneKeyDown, onDragEnter: dropzone.onZoneDragEnter, onDragOver: dropzone.onZoneDragOver, onDragLeave: dropzone.onZoneDragLeave, onDrop: dropzone.onZoneDrop, children: [_jsx("input", { ref: dropzone.inputRef, type: "file", multiple: true, accept: accept, className: "jini-file-dropzone__input", onClick: (event) => {
|
|
17
|
+
// The input is nested inside the zone div so a real user
|
|
18
|
+
// click on it (e.g. via `openPicker`'s own `input.click()`
|
|
19
|
+
// call) would otherwise bubble straight back into the zone's
|
|
20
|
+
// own `onClick={dropzone.openPicker}`, re-triggering it and
|
|
21
|
+
// opening the file dialog a second time.
|
|
22
|
+
event.stopPropagation();
|
|
23
|
+
dropzone.onInputClick();
|
|
24
|
+
}, onChange: dropzone.onInputChange, ...directoryInputProps }), _jsx("span", { className: "jini-file-dropzone__icon", children: _jsx(Icon, { name: "upload", size: 19 }) }), _jsx("span", { className: "jini-file-dropzone__prompt", children: zoneText }), hint ? _jsx("span", { className: "jini-file-dropzone__hint", children: hint }) : null] }));
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=FileDropzoneZone.js.map
|
|
@@ -54,26 +54,26 @@ function buildWrapperElement(doc, node) {
|
|
|
54
54
|
* (each moved once, no copying).
|
|
55
55
|
*/
|
|
56
56
|
export function applyCanvasContentWrapper(body, chain) {
|
|
57
|
-
if (!chain
|
|
57
|
+
if (!chain)
|
|
58
|
+
return;
|
|
59
|
+
// `[]` is the same no-op as `undefined`; reading the innermost node here doubles as that length check.
|
|
60
|
+
const innermostNode = chain[chain.length - 1];
|
|
61
|
+
if (!innermostNode)
|
|
58
62
|
return;
|
|
59
63
|
// Re-entrancy guard — see WRAPPER_ROOT_MARKER's own doc.
|
|
60
64
|
if (body.querySelector(`[${WRAPPER_ROOT_MARKER}]`))
|
|
61
65
|
return;
|
|
62
66
|
const doc = body.ownerDocument;
|
|
63
|
-
// Built innermost-first via `reduceRight` (each level's element wraps
|
|
64
|
-
//
|
|
65
|
-
//
|
|
66
|
-
//
|
|
67
|
-
|
|
68
|
-
const outermost = chain.reduceRight((child, node) => {
|
|
67
|
+
// Built innermost-first via `reduceRight` over the remaining ancestors (each level's element wraps
|
|
68
|
+
// the previous result), seeded with the innermost level itself — so both ends of the chain are
|
|
69
|
+
// plain `HTMLElement`s with no "maybe undefined" result to guard. (The old seed was `undefined`,
|
|
70
|
+
// which forced an `if (!outermost || !innermost) return` the length guard above made unreachable.)
|
|
71
|
+
const innermost = buildWrapperElement(doc, innermostNode);
|
|
72
|
+
const outermost = chain.slice(0, -1).reduceRight((child, node) => {
|
|
69
73
|
const el = buildWrapperElement(doc, node);
|
|
70
|
-
|
|
71
|
-
el.appendChild(child);
|
|
72
|
-
innermost ??= el;
|
|
74
|
+
el.appendChild(child);
|
|
73
75
|
return el;
|
|
74
|
-
},
|
|
75
|
-
if (!outermost || !innermost)
|
|
76
|
-
return; // Unreachable given the `chain.length === 0` guard above.
|
|
76
|
+
}, innermost);
|
|
77
77
|
outermost.setAttribute(WRAPPER_ROOT_MARKER, '');
|
|
78
78
|
// Move body's existing children into the innermost wrapper level, preserving order. Snapshotted
|
|
79
79
|
// into an array first — `body.childNodes` is a LIVE collection that would shrink out from under a
|
|
@@ -224,39 +224,60 @@ export function applyCanvasEmbedPlaceholders(body, describe) {
|
|
|
224
224
|
// Skip existing embed cards and all chrome before calling the host. Runtime cards still
|
|
225
225
|
// re-describe their direct marker so theme changes can refresh its bounded footprint.
|
|
226
226
|
const existingCard = el.closest(`[${CARD_ROOT_MARKER}]`);
|
|
227
|
-
if (existingCard && (
|
|
228
|
-
|| el.parentElement !== existingCard || el.hasAttribute(CARD_CHROME_MARKER)))
|
|
227
|
+
if (existingCard && !canRefreshRuntimeCard({ el, card: existingCard }, {}))
|
|
229
228
|
continue;
|
|
230
229
|
const descriptor = describe(el);
|
|
231
230
|
if (!descriptor)
|
|
232
231
|
continue;
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
const card = buildPlaceholderCard(doc, descriptor);
|
|
242
|
-
// Respect the author's own box (e.g. `style="max-width:600px"` on the marker) by carrying its
|
|
243
|
-
// inline style onto the card BEFORE the card's own chrome declarations, so same-named properties
|
|
244
|
-
// in `CARD_STYLE` win on the cascade's normal "last declaration wins" rule while anything the
|
|
245
|
-
// author set that `CARD_STYLE` doesn't touch (like `max-width`) still applies unopposed. Guarded
|
|
246
|
-
// on presence so a marker with no `style` attribute at all is a no-op, not a leading `;`.
|
|
247
|
-
const authoredStyle = el.getAttribute('style');
|
|
248
|
-
if (authoredStyle && descriptor.presentation !== 'runtime')
|
|
249
|
-
card.setAttribute('style', `${authoredStyle};${card.getAttribute('style')}`);
|
|
250
|
-
applyResolvedMaxWidth(el, card);
|
|
232
|
+
updatePlaceholder({ el, doc, descriptor, existingCard }, {});
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
function canRefreshRuntimeCard({ el, card }, _options = {}) {
|
|
236
|
+
return card.hasAttribute(CARD_RUNTIME_MARKER) && el.parentElement === card && !el.hasAttribute(CARD_CHROME_MARKER);
|
|
237
|
+
}
|
|
238
|
+
function updatePlaceholder({ el, doc, descriptor, existingCard }, _options = {}) {
|
|
239
|
+
if (existingCard) {
|
|
251
240
|
if (descriptor.presentation === 'runtime')
|
|
252
|
-
applyRuntimeFootprint(el,
|
|
253
|
-
|
|
254
|
-
card.appendChild(el); // Moves the SAME node (auto-detaches from `parent`) — never cloned.
|
|
255
|
-
ensureOverlayRule(doc);
|
|
241
|
+
applyRuntimeFootprint(el, existingCard, descriptor);
|
|
242
|
+
return;
|
|
256
243
|
}
|
|
244
|
+
const parent = el.parentNode;
|
|
245
|
+
if (!parent)
|
|
246
|
+
return; // Unreachable for a live `body` descendant; defensive only.
|
|
247
|
+
const card = buildPlaceholderCard(doc, descriptor);
|
|
248
|
+
// Respect the author's own box (e.g. `style="max-width:600px"` on the marker) by carrying its
|
|
249
|
+
// inline style onto the card BEFORE the card's own chrome declarations, so same-named properties
|
|
250
|
+
// in `CARD_STYLE` win on the cascade's normal "last declaration wins" rule while anything the
|
|
251
|
+
// author set that `CARD_STYLE` doesn't touch (like `max-width`) still applies unopposed. Guarded
|
|
252
|
+
// on presence so a marker with no `style` attribute at all is a no-op, not a leading `;`.
|
|
253
|
+
const authoredStyle = el.getAttribute('style');
|
|
254
|
+
if (authoredStyle && descriptor.presentation !== 'runtime')
|
|
255
|
+
card.setAttribute('style', `${authoredStyle};${card.getAttribute('style')}`);
|
|
256
|
+
applyResolvedMaxWidth(el, card);
|
|
257
|
+
if (descriptor.presentation === 'runtime')
|
|
258
|
+
applyRuntimeFootprint(el, card, descriptor);
|
|
259
|
+
parent.insertBefore(card, el);
|
|
260
|
+
card.appendChild(el); // Moves the SAME node (auto-detaches from `parent`) — never cloned.
|
|
261
|
+
ensureOverlayRule(doc);
|
|
257
262
|
}
|
|
258
263
|
/** Geometry belongs to canvas DOM only; arbitrary transforms/min-height cannot defeat the clamp. */
|
|
259
264
|
function applyRuntimeFootprint(el, card, descriptor) {
|
|
265
|
+
const resolved = measureAuthoredHeight({ el }, {});
|
|
266
|
+
const native = el.getAttribute('height');
|
|
267
|
+
const declared = descriptor.declaredHeight ?? (resolved?.endsWith('px') ? Number.parseFloat(resolved) : undefined);
|
|
268
|
+
card.style.height = `${editorBlockHeight({ declaredHeight: declared, nativeHeight: native ? Number(native) : undefined, inline: descriptor.inline }, {})}px`;
|
|
269
|
+
card.style.minHeight = '0';
|
|
270
|
+
card.style.maxHeight = descriptor.inline ? '160px' : '960px';
|
|
271
|
+
card.style.overflow = 'hidden';
|
|
272
|
+
if (descriptor.inline) {
|
|
273
|
+
card.style.display = 'inline-flex';
|
|
274
|
+
card.style.verticalAlign = 'middle';
|
|
275
|
+
}
|
|
276
|
+
// The marker is the selectable hit surface, never an authored layout/transform or media view.
|
|
277
|
+
el.style.setProperty('transform', 'none', 'important');
|
|
278
|
+
el.style.setProperty('overflow', 'hidden', 'important');
|
|
279
|
+
}
|
|
280
|
+
function measureAuthoredHeight({ el }, _options = {}) {
|
|
260
281
|
// Re-measure the authored shell after theme links settle, without our selection overlay's
|
|
261
282
|
// !important auto-height masking its declarations. No component/model styles are changed.
|
|
262
283
|
const overlay = el.ownerDocument.head.querySelector(`style[${OVERLAY_STYLE_MARKER}]`);
|
|
@@ -272,18 +293,6 @@ function applyRuntimeFootprint(el, card, descriptor) {
|
|
|
272
293
|
if (sheet)
|
|
273
294
|
sheet.disabled = wasDisabled ?? false;
|
|
274
295
|
}
|
|
275
|
-
|
|
276
|
-
const declared = descriptor.declaredHeight ?? (resolved?.endsWith('px') ? Number.parseFloat(resolved) : undefined);
|
|
277
|
-
card.style.height = `${editorBlockHeight({ declaredHeight: declared, nativeHeight: native ? Number(native) : undefined, inline: descriptor.inline }, {})}px`;
|
|
278
|
-
card.style.minHeight = '0';
|
|
279
|
-
card.style.maxHeight = descriptor.inline ? '160px' : '960px';
|
|
280
|
-
card.style.overflow = 'hidden';
|
|
281
|
-
if (descriptor.inline) {
|
|
282
|
-
card.style.display = 'inline-flex';
|
|
283
|
-
card.style.verticalAlign = 'middle';
|
|
284
|
-
}
|
|
285
|
-
// The marker is the selectable hit surface, never an authored layout/transform or media view.
|
|
286
|
-
el.style.setProperty('transform', 'none', 'important');
|
|
287
|
-
el.style.setProperty('overflow', 'hidden', 'important');
|
|
296
|
+
return resolved;
|
|
288
297
|
}
|
|
289
298
|
//# sourceMappingURL=canvas-embed-placeholders.js.map
|