@cratis/scene.primereact 4.5.0 → 4.7.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/.storybook/preview.tsx +8 -1
- package/EnumerationResolution.ts +7 -0
- package/README.md +42 -10
- package/chart/ChartGallery.stories.tsx +63 -0
- package/chart/ChartType.ts +14 -0
- package/chart/ChartTypeResolution.ts +14 -0
- package/chart/PrimeChart.tsx +62 -0
- package/chart/chartHasData.ts +22 -0
- package/chart/chartTypeChoices.ts +32 -0
- package/chart/index.ts +7 -0
- package/chart/resolveChartType.ts +61 -0
- package/chart/useChart.ts +61 -0
- package/data/DataGallery.stories.tsx +6 -0
- package/data/DataScrollerRow.tsx +35 -0
- package/data/PrimeDataScroller.tsx +84 -0
- package/data/PrimeTreeTable.tsx +145 -0
- package/data/TreeTableCheckState.ts +9 -0
- package/data/TreeTableRow.ts +22 -0
- package/data/TreeTableRowView.tsx +86 -0
- package/data/TreeTableSelectionMode.ts +10 -0
- package/data/checkboxSelection.ts +92 -0
- package/data/index.ts +4 -0
- package/data/isSerializedLegacyElement.ts +30 -0
- package/data/readableValue.ts +32 -0
- package/data/selectionKeysOf.ts +40 -0
- package/data/treeTableRows.ts +32 -0
- package/data/useIncrementalLoad.ts +36 -0
- package/data/useLoadOnReach.ts +31 -0
- package/data/useTreeGridNavigation.ts +81 -0
- package/dist/cjs/chart/ChartType.js +18 -0
- package/dist/cjs/chart/ChartType.js.map +1 -0
- package/dist/cjs/chart/PrimeChart.js +92 -0
- package/dist/cjs/chart/PrimeChart.js.map +1 -0
- package/dist/cjs/chart/chartHasData.js +24 -0
- package/dist/cjs/chart/chartHasData.js.map +1 -0
- package/dist/cjs/chart/chartTypeChoices.js +43 -0
- package/dist/cjs/chart/chartTypeChoices.js.map +1 -0
- package/dist/cjs/chart/resolveChartType.js +69 -0
- package/dist/cjs/chart/resolveChartType.js.map +1 -0
- package/dist/cjs/chart/useChart.js +62 -0
- package/dist/cjs/chart/useChart.js.map +1 -0
- package/dist/cjs/data/DataScrollerRow.js +50 -0
- package/dist/cjs/data/DataScrollerRow.js.map +1 -0
- package/dist/cjs/data/PrimeDataScroller.js +120 -0
- package/dist/cjs/data/PrimeDataScroller.js.map +1 -0
- package/dist/cjs/data/PrimeTreeTable.js +217 -0
- package/dist/cjs/data/PrimeTreeTable.js.map +1 -0
- package/dist/cjs/data/TreeTableCheckState.js +13 -0
- package/dist/cjs/data/TreeTableCheckState.js.map +1 -0
- package/dist/cjs/data/TreeTableRowView.js +76 -0
- package/dist/cjs/data/TreeTableRowView.js.map +1 -0
- package/dist/cjs/data/TreeTableSelectionMode.js +14 -0
- package/dist/cjs/data/TreeTableSelectionMode.js.map +1 -0
- package/dist/cjs/data/checkboxSelection.js +88 -0
- package/dist/cjs/data/checkboxSelection.js.map +1 -0
- package/dist/cjs/data/isSerializedLegacyElement.js +30 -0
- package/dist/cjs/data/isSerializedLegacyElement.js.map +1 -0
- package/dist/cjs/data/readableValue.js +31 -0
- package/dist/cjs/data/readableValue.js.map +1 -0
- package/dist/cjs/data/selectionKeysOf.js +40 -0
- package/dist/cjs/data/selectionKeysOf.js.map +1 -0
- package/dist/cjs/data/treeTableRows.js +42 -0
- package/dist/cjs/data/treeTableRows.js.map +1 -0
- package/dist/cjs/data/useIncrementalLoad.js +46 -0
- package/dist/cjs/data/useIncrementalLoad.js.map +1 -0
- package/dist/cjs/data/useLoadOnReach.js +42 -0
- package/dist/cjs/data/useLoadOnReach.js.map +1 -0
- package/dist/cjs/data/useTreeGridNavigation.js +75 -0
- package/dist/cjs/data/useTreeGridNavigation.js.map +1 -0
- package/dist/cjs/editor/PrimeEditor.js +96 -0
- package/dist/cjs/editor/PrimeEditor.js.map +1 -0
- package/dist/cjs/editor/QuillLoaderContext.js +10 -0
- package/dist/cjs/editor/QuillLoaderContext.js.map +1 -0
- package/dist/cjs/editor/QuillLoaderProvider.js +21 -0
- package/dist/cjs/editor/QuillLoaderProvider.js.map +1 -0
- package/dist/cjs/editor/applyHtml.js +25 -0
- package/dist/cjs/editor/applyHtml.js.map +1 -0
- package/dist/cjs/editor/characterCount.js +10 -0
- package/dist/cjs/editor/characterCount.js.map +1 -0
- package/dist/cjs/editor/htmlToPlainText.js +101 -0
- package/dist/cjs/editor/htmlToPlainText.js.map +1 -0
- package/dist/cjs/editor/renderSafeNodes.js +35 -0
- package/dist/cjs/editor/renderSafeNodes.js.map +1 -0
- package/dist/cjs/editor/safeUrls.js +44 -0
- package/dist/cjs/editor/safeUrls.js.map +1 -0
- package/dist/cjs/editor/sanitizeHtml.js +140 -0
- package/dist/cjs/editor/sanitizeHtml.js.map +1 -0
- package/dist/cjs/editor/serializeSafeNodes.js +33 -0
- package/dist/cjs/editor/serializeSafeNodes.js.map +1 -0
- package/dist/cjs/editor/toolbarLayout.js +35 -0
- package/dist/cjs/editor/toolbarLayout.js.map +1 -0
- package/dist/cjs/editor/useQuillEditor.js +137 -0
- package/dist/cjs/editor/useQuillEditor.js.map +1 -0
- package/dist/cjs/file/FileUploadContext.js +13 -0
- package/dist/cjs/file/FileUploadContext.js.map +1 -0
- package/dist/cjs/file/FileUploadHandlerProvider.js +25 -0
- package/dist/cjs/file/FileUploadHandlerProvider.js.map +1 -0
- package/dist/cjs/file/FileUploadMode.js +13 -0
- package/dist/cjs/file/FileUploadMode.js.map +1 -0
- package/dist/cjs/file/PrimeFileUpload.js +161 -0
- package/dist/cjs/file/PrimeFileUpload.js.map +1 -0
- package/dist/cjs/file/postFiles.js +31 -0
- package/dist/cjs/file/postFiles.js.map +1 -0
- package/dist/cjs/file/resolveUploadTarget.js +68 -0
- package/dist/cjs/file/resolveUploadTarget.js.map +1 -0
- package/dist/cjs/file/useUploadSession.js +62 -0
- package/dist/cjs/file/useUploadSession.js.map +1 -0
- package/dist/cjs/form/MultiStateGlyph.js +59 -0
- package/dist/cjs/form/MultiStateGlyph.js.map +1 -0
- package/dist/cjs/form/PrimeMultiStateCheckbox.js +123 -0
- package/dist/cjs/form/PrimeMultiStateCheckbox.js.map +1 -0
- package/dist/cjs/form/multiStateOptions.js +77 -0
- package/dist/cjs/form/multiStateOptions.js.map +1 -0
- package/dist/cjs/form/multiStateStates.js +32 -0
- package/dist/cjs/form/multiStateStates.js.map +1 -0
- package/dist/cjs/form/useMultiStateSelection.js +51 -0
- package/dist/cjs/form/useMultiStateSelection.js.map +1 -0
- package/dist/cjs/index.js +44 -0
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/legacyEnumerationChoices.js +39 -0
- package/dist/cjs/legacyEnumerationChoices.js.map +1 -0
- package/dist/cjs/loadQuill/index.js +22 -0
- package/dist/cjs/loadQuill/index.js.map +1 -0
- package/dist/cjs/primeReactComponents.js +15 -0
- package/dist/cjs/primeReactComponents.js.map +1 -1
- package/dist/cjs/primeReactDescriptors.js +400 -0
- package/dist/cjs/primeReactDescriptors.js.map +1 -0
- package/dist/cjs/primeReactPackage.js +8 -0
- package/dist/cjs/primeReactPackage.js.map +1 -1
- package/dist/cjs/properties.js +11 -0
- package/dist/cjs/properties.js.map +1 -1
- package/dist/cjs/resolveEnumeration.js +55 -0
- package/dist/cjs/resolveEnumeration.js.map +1 -0
- package/dist/cjs/structurallyEqual.js +27 -0
- package/dist/cjs/structurallyEqual.js.map +1 -0
- package/dist/cjs/treeNodes.js +42 -7
- package/dist/cjs/treeNodes.js.map +1 -1
- package/dist/cjs/useResettingState.js +47 -0
- package/dist/cjs/useResettingState.js.map +1 -0
- package/dist/cjs/useStructuralValue.js +20 -0
- package/dist/cjs/useStructuralValue.js.map +1 -0
- package/dist/esm/EnumerationResolution.d.ts +9 -0
- package/dist/esm/EnumerationResolution.d.ts.map +1 -0
- package/dist/esm/EnumerationResolution.js +2 -0
- package/dist/esm/EnumerationResolution.js.map +1 -0
- package/dist/esm/chart/ChartGallery.stories.d.ts +14 -0
- package/dist/esm/chart/ChartGallery.stories.d.ts.map +1 -0
- package/dist/esm/chart/ChartGallery.stories.js +47 -0
- package/dist/esm/chart/ChartGallery.stories.js.map +1 -0
- package/dist/esm/chart/ChartType.d.ts +11 -0
- package/dist/esm/chart/ChartType.d.ts.map +1 -0
- package/dist/esm/chart/ChartType.js +16 -0
- package/dist/esm/chart/ChartType.js.map +1 -0
- package/dist/esm/chart/ChartTypeResolution.d.ts +10 -0
- package/dist/esm/chart/ChartTypeResolution.d.ts.map +1 -0
- package/dist/esm/chart/ChartTypeResolution.js +2 -0
- package/dist/esm/chart/ChartTypeResolution.js.map +1 -0
- package/dist/esm/chart/PrimeChart.d.ts +3 -0
- package/dist/esm/chart/PrimeChart.d.ts.map +1 -0
- package/dist/esm/chart/PrimeChart.js +90 -0
- package/dist/esm/chart/PrimeChart.js.map +1 -0
- package/dist/esm/chart/chartHasData.d.ts +2 -0
- package/dist/esm/chart/chartHasData.d.ts.map +1 -0
- package/dist/esm/chart/chartHasData.js +22 -0
- package/dist/esm/chart/chartHasData.js.map +1 -0
- package/dist/esm/chart/chartTypeChoices.d.ts +3 -0
- package/dist/esm/chart/chartTypeChoices.d.ts.map +1 -0
- package/dist/esm/chart/chartTypeChoices.js +41 -0
- package/dist/esm/chart/chartTypeChoices.js.map +1 -0
- package/dist/esm/chart/index.d.ts +5 -0
- package/dist/esm/chart/index.d.ts.map +1 -0
- package/dist/esm/chart/index.js +5 -0
- package/dist/esm/chart/index.js.map +1 -0
- package/dist/esm/chart/resolveChartType.d.ts +6 -0
- package/dist/esm/chart/resolveChartType.d.ts.map +1 -0
- package/dist/esm/chart/resolveChartType.js +66 -0
- package/dist/esm/chart/resolveChartType.js.map +1 -0
- package/dist/esm/chart/useChart.d.ts +4 -0
- package/dist/esm/chart/useChart.d.ts.map +1 -0
- package/dist/esm/chart/useChart.js +60 -0
- package/dist/esm/chart/useChart.js.map +1 -0
- package/dist/esm/data/DataGallery.stories.d.ts.map +1 -1
- package/dist/esm/data/DataGallery.stories.js +6 -0
- package/dist/esm/data/DataGallery.stories.js.map +1 -1
- package/dist/esm/data/DataScrollerRow.d.ts +4 -0
- package/dist/esm/data/DataScrollerRow.d.ts.map +1 -0
- package/dist/esm/data/DataScrollerRow.js +48 -0
- package/dist/esm/data/DataScrollerRow.js.map +1 -0
- package/dist/esm/data/PrimeDataScroller.d.ts +3 -0
- package/dist/esm/data/PrimeDataScroller.d.ts.map +1 -0
- package/dist/esm/data/PrimeDataScroller.js +118 -0
- package/dist/esm/data/PrimeDataScroller.js.map +1 -0
- package/dist/esm/data/PrimeTreeTable.d.ts +3 -0
- package/dist/esm/data/PrimeTreeTable.d.ts.map +1 -0
- package/dist/esm/data/PrimeTreeTable.js +215 -0
- package/dist/esm/data/PrimeTreeTable.js.map +1 -0
- package/dist/esm/data/TreeTableCheckState.d.ts +6 -0
- package/dist/esm/data/TreeTableCheckState.d.ts.map +1 -0
- package/dist/esm/data/TreeTableCheckState.js +11 -0
- package/dist/esm/data/TreeTableCheckState.js.map +1 -0
- package/dist/esm/data/TreeTableRow.d.ts +10 -0
- package/dist/esm/data/TreeTableRow.d.ts.map +1 -0
- package/dist/esm/data/TreeTableRow.js +2 -0
- package/dist/esm/data/TreeTableRow.js.map +1 -0
- package/dist/esm/data/TreeTableRowView.d.ts +21 -0
- package/dist/esm/data/TreeTableRowView.d.ts.map +1 -0
- package/dist/esm/data/TreeTableRowView.js +74 -0
- package/dist/esm/data/TreeTableRowView.js.map +1 -0
- package/dist/esm/data/TreeTableSelectionMode.d.ts +7 -0
- package/dist/esm/data/TreeTableSelectionMode.d.ts.map +1 -0
- package/dist/esm/data/TreeTableSelectionMode.js +12 -0
- package/dist/esm/data/TreeTableSelectionMode.js.map +1 -0
- package/dist/esm/data/checkboxSelection.d.ts +9 -0
- package/dist/esm/data/checkboxSelection.d.ts.map +1 -0
- package/dist/esm/data/checkboxSelection.js +85 -0
- package/dist/esm/data/checkboxSelection.js.map +1 -0
- package/dist/esm/data/index.d.ts +4 -0
- package/dist/esm/data/index.d.ts.map +1 -1
- package/dist/esm/data/index.js +4 -0
- package/dist/esm/data/index.js.map +1 -1
- package/dist/esm/data/isSerializedLegacyElement.d.ts +3 -0
- package/dist/esm/data/isSerializedLegacyElement.d.ts.map +1 -0
- package/dist/esm/data/isSerializedLegacyElement.js +27 -0
- package/dist/esm/data/isSerializedLegacyElement.js.map +1 -0
- package/dist/esm/data/readableValue.d.ts +2 -0
- package/dist/esm/data/readableValue.d.ts.map +1 -0
- package/dist/esm/data/readableValue.js +29 -0
- package/dist/esm/data/readableValue.js.map +1 -0
- package/dist/esm/data/selectionKeysOf.d.ts +2 -0
- package/dist/esm/data/selectionKeysOf.d.ts.map +1 -0
- package/dist/esm/data/selectionKeysOf.js +38 -0
- package/dist/esm/data/selectionKeysOf.js.map +1 -0
- package/dist/esm/data/treeTableRows.d.ts +6 -0
- package/dist/esm/data/treeTableRows.d.ts.map +1 -0
- package/dist/esm/data/treeTableRows.js +38 -0
- package/dist/esm/data/treeTableRows.js.map +1 -0
- package/dist/esm/data/useIncrementalLoad.d.ts +6 -0
- package/dist/esm/data/useIncrementalLoad.d.ts.map +1 -0
- package/dist/esm/data/useIncrementalLoad.js +44 -0
- package/dist/esm/data/useIncrementalLoad.js.map +1 -0
- package/dist/esm/data/useLoadOnReach.d.ts +3 -0
- package/dist/esm/data/useLoadOnReach.d.ts.map +1 -0
- package/dist/esm/data/useLoadOnReach.js +40 -0
- package/dist/esm/data/useLoadOnReach.js.map +1 -0
- package/dist/esm/data/useTreeGridNavigation.d.ts +17 -0
- package/dist/esm/data/useTreeGridNavigation.d.ts.map +1 -0
- package/dist/esm/data/useTreeGridNavigation.js +73 -0
- package/dist/esm/data/useTreeGridNavigation.js.map +1 -0
- package/dist/esm/editor/PrimeEditor.d.ts +3 -0
- package/dist/esm/editor/PrimeEditor.d.ts.map +1 -0
- package/dist/esm/editor/PrimeEditor.js +94 -0
- package/dist/esm/editor/PrimeEditor.js.map +1 -0
- package/dist/esm/editor/QuillConstructor.d.ts +4 -0
- package/dist/esm/editor/QuillConstructor.d.ts.map +1 -0
- package/dist/esm/editor/QuillConstructor.js +2 -0
- package/dist/esm/editor/QuillConstructor.js.map +1 -0
- package/dist/esm/editor/QuillEditorOptions.d.ts +13 -0
- package/dist/esm/editor/QuillEditorOptions.d.ts.map +1 -0
- package/dist/esm/editor/QuillEditorOptions.js +2 -0
- package/dist/esm/editor/QuillEditorOptions.js.map +1 -0
- package/dist/esm/editor/QuillEditorState.d.ts +6 -0
- package/dist/esm/editor/QuillEditorState.d.ts.map +1 -0
- package/dist/esm/editor/QuillEditorState.js +2 -0
- package/dist/esm/editor/QuillEditorState.js.map +1 -0
- package/dist/esm/editor/QuillInstance.d.ts +16 -0
- package/dist/esm/editor/QuillInstance.d.ts.map +1 -0
- package/dist/esm/editor/QuillInstance.js +2 -0
- package/dist/esm/editor/QuillInstance.js.map +1 -0
- package/dist/esm/editor/QuillLoader.d.ts +5 -0
- package/dist/esm/editor/QuillLoader.d.ts.map +1 -0
- package/dist/esm/editor/QuillLoader.js +2 -0
- package/dist/esm/editor/QuillLoader.js.map +1 -0
- package/dist/esm/editor/QuillLoaderContext.d.ts +3 -0
- package/dist/esm/editor/QuillLoaderContext.d.ts.map +1 -0
- package/dist/esm/editor/QuillLoaderContext.js +8 -0
- package/dist/esm/editor/QuillLoaderContext.js.map +1 -0
- package/dist/esm/editor/QuillLoaderProvider.d.ts +8 -0
- package/dist/esm/editor/QuillLoaderProvider.d.ts.map +1 -0
- package/dist/esm/editor/QuillLoaderProvider.js +19 -0
- package/dist/esm/editor/QuillLoaderProvider.js.map +1 -0
- package/dist/esm/editor/QuillOptions.d.ts +9 -0
- package/dist/esm/editor/QuillOptions.d.ts.map +1 -0
- package/dist/esm/editor/QuillOptions.js +2 -0
- package/dist/esm/editor/QuillOptions.js.map +1 -0
- package/dist/esm/editor/SafeElement.d.ts +7 -0
- package/dist/esm/editor/SafeElement.d.ts.map +1 -0
- package/dist/esm/editor/SafeElement.js +2 -0
- package/dist/esm/editor/SafeElement.js.map +1 -0
- package/dist/esm/editor/SafeNode.d.ts +3 -0
- package/dist/esm/editor/SafeNode.d.ts.map +1 -0
- package/dist/esm/editor/SafeNode.js +2 -0
- package/dist/esm/editor/SafeNode.js.map +1 -0
- package/dist/esm/editor/applyHtml.d.ts +3 -0
- package/dist/esm/editor/applyHtml.d.ts.map +1 -0
- package/dist/esm/editor/applyHtml.js +23 -0
- package/dist/esm/editor/applyHtml.js.map +1 -0
- package/dist/esm/editor/characterCount.d.ts +3 -0
- package/dist/esm/editor/characterCount.d.ts.map +1 -0
- package/dist/esm/editor/characterCount.js +8 -0
- package/dist/esm/editor/characterCount.js.map +1 -0
- package/dist/esm/editor/htmlToPlainText.d.ts +2 -0
- package/dist/esm/editor/htmlToPlainText.d.ts.map +1 -0
- package/dist/esm/editor/htmlToPlainText.js +99 -0
- package/dist/esm/editor/htmlToPlainText.js.map +1 -0
- package/dist/esm/editor/index.d.ts +14 -0
- package/dist/esm/editor/index.d.ts.map +1 -0
- package/dist/esm/editor/index.js +14 -0
- package/dist/esm/editor/index.js.map +1 -0
- package/dist/esm/editor/renderSafeNodes.d.ts +4 -0
- package/dist/esm/editor/renderSafeNodes.d.ts.map +1 -0
- package/dist/esm/editor/renderSafeNodes.js +33 -0
- package/dist/esm/editor/renderSafeNodes.js.map +1 -0
- package/dist/esm/editor/safeUrls.d.ts +3 -0
- package/dist/esm/editor/safeUrls.d.ts.map +1 -0
- package/dist/esm/editor/safeUrls.js +41 -0
- package/dist/esm/editor/safeUrls.js.map +1 -0
- package/dist/esm/editor/sanitizeHtml.d.ts +3 -0
- package/dist/esm/editor/sanitizeHtml.d.ts.map +1 -0
- package/dist/esm/editor/sanitizeHtml.js +138 -0
- package/dist/esm/editor/sanitizeHtml.js.map +1 -0
- package/dist/esm/editor/serializeSafeNodes.d.ts +3 -0
- package/dist/esm/editor/serializeSafeNodes.d.ts.map +1 -0
- package/dist/esm/editor/serializeSafeNodes.js +31 -0
- package/dist/esm/editor/serializeSafeNodes.js.map +1 -0
- package/dist/esm/editor/toolbarLayout.d.ts +2 -0
- package/dist/esm/editor/toolbarLayout.d.ts.map +1 -0
- package/dist/esm/editor/toolbarLayout.js +33 -0
- package/dist/esm/editor/toolbarLayout.js.map +1 -0
- package/dist/esm/editor/useQuillEditor.d.ts +4 -0
- package/dist/esm/editor/useQuillEditor.d.ts.map +1 -0
- package/dist/esm/editor/useQuillEditor.js +135 -0
- package/dist/esm/editor/useQuillEditor.js.map +1 -0
- package/dist/esm/file/FileGallery.stories.d.ts +19 -0
- package/dist/esm/file/FileGallery.stories.d.ts.map +1 -0
- package/dist/esm/file/FileGallery.stories.js +23 -0
- package/dist/esm/file/FileGallery.stories.js.map +1 -0
- package/dist/esm/file/FileUploadContext.d.ts +7 -0
- package/dist/esm/file/FileUploadContext.d.ts.map +1 -0
- package/dist/esm/file/FileUploadContext.js +11 -0
- package/dist/esm/file/FileUploadContext.js.map +1 -0
- package/dist/esm/file/FileUploadHandler.d.ts +4 -0
- package/dist/esm/file/FileUploadHandler.d.ts.map +1 -0
- package/dist/esm/file/FileUploadHandler.js +2 -0
- package/dist/esm/file/FileUploadHandler.js.map +1 -0
- package/dist/esm/file/FileUploadHandlerProvider.d.ts +9 -0
- package/dist/esm/file/FileUploadHandlerProvider.d.ts.map +1 -0
- package/dist/esm/file/FileUploadHandlerProvider.js +23 -0
- package/dist/esm/file/FileUploadHandlerProvider.js.map +1 -0
- package/dist/esm/file/FileUploadMode.d.ts +6 -0
- package/dist/esm/file/FileUploadMode.d.ts.map +1 -0
- package/dist/esm/file/FileUploadMode.js +11 -0
- package/dist/esm/file/FileUploadMode.js.map +1 -0
- package/dist/esm/file/PrimeFileUpload.d.ts +3 -0
- package/dist/esm/file/PrimeFileUpload.d.ts.map +1 -0
- package/dist/esm/file/PrimeFileUpload.js +159 -0
- package/dist/esm/file/PrimeFileUpload.js.map +1 -0
- package/dist/esm/file/UploadStatus.d.ts +5 -0
- package/dist/esm/file/UploadStatus.d.ts.map +1 -0
- package/dist/esm/file/UploadStatus.js +2 -0
- package/dist/esm/file/UploadStatus.js.map +1 -0
- package/dist/esm/file/UploadTarget.d.ts +8 -0
- package/dist/esm/file/UploadTarget.d.ts.map +1 -0
- package/dist/esm/file/UploadTarget.js +2 -0
- package/dist/esm/file/UploadTarget.js.map +1 -0
- package/dist/esm/file/index.d.ts +7 -0
- package/dist/esm/file/index.d.ts.map +1 -0
- package/dist/esm/file/index.js +7 -0
- package/dist/esm/file/index.js.map +1 -0
- package/dist/esm/file/postFiles.d.ts +2 -0
- package/dist/esm/file/postFiles.d.ts.map +1 -0
- package/dist/esm/file/postFiles.js +29 -0
- package/dist/esm/file/postFiles.js.map +1 -0
- package/dist/esm/file/resolveUploadTarget.d.ts +3 -0
- package/dist/esm/file/resolveUploadTarget.d.ts.map +1 -0
- package/dist/esm/file/resolveUploadTarget.js +66 -0
- package/dist/esm/file/resolveUploadTarget.js.map +1 -0
- package/dist/esm/file/useUploadSession.d.ts +10 -0
- package/dist/esm/file/useUploadSession.d.ts.map +1 -0
- package/dist/esm/file/useUploadSession.js +60 -0
- package/dist/esm/file/useUploadSession.js.map +1 -0
- package/dist/esm/form/FormGallery.stories.d.ts.map +1 -1
- package/dist/esm/form/FormGallery.stories.js +9 -0
- package/dist/esm/form/FormGallery.stories.js.map +1 -1
- package/dist/esm/form/MultiStateGlyph.d.ts +8 -0
- package/dist/esm/form/MultiStateGlyph.d.ts.map +1 -0
- package/dist/esm/form/MultiStateGlyph.js +57 -0
- package/dist/esm/form/MultiStateGlyph.js.map +1 -0
- package/dist/esm/form/MultiStateOption.d.ts +7 -0
- package/dist/esm/form/MultiStateOption.d.ts.map +1 -0
- package/dist/esm/form/MultiStateOption.js +2 -0
- package/dist/esm/form/MultiStateOption.js.map +1 -0
- package/dist/esm/form/PrimeMultiStateCheckbox.d.ts +3 -0
- package/dist/esm/form/PrimeMultiStateCheckbox.d.ts.map +1 -0
- package/dist/esm/form/PrimeMultiStateCheckbox.js +121 -0
- package/dist/esm/form/PrimeMultiStateCheckbox.js.map +1 -0
- package/dist/esm/form/index.d.ts +1 -0
- package/dist/esm/form/index.d.ts.map +1 -1
- package/dist/esm/form/index.js +1 -0
- package/dist/esm/form/index.js.map +1 -1
- package/dist/esm/form/multiStateOptions.d.ts +4 -0
- package/dist/esm/form/multiStateOptions.d.ts.map +1 -0
- package/dist/esm/form/multiStateOptions.js +75 -0
- package/dist/esm/form/multiStateOptions.js.map +1 -0
- package/dist/esm/form/multiStateStates.d.ts +4 -0
- package/dist/esm/form/multiStateStates.d.ts.map +1 -0
- package/dist/esm/form/multiStateStates.js +30 -0
- package/dist/esm/form/multiStateStates.js.map +1 -0
- package/dist/esm/form/useMultiStateSelection.d.ts +6 -0
- package/dist/esm/form/useMultiStateSelection.d.ts.map +1 -0
- package/dist/esm/form/useMultiStateSelection.js +49 -0
- package/dist/esm/form/useMultiStateSelection.js.map +1 -0
- package/dist/esm/index.d.ts +4 -0
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +22 -2
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/legacyEnumerationChoices.d.ts +3 -0
- package/dist/esm/legacyEnumerationChoices.d.ts.map +1 -0
- package/dist/esm/legacyEnumerationChoices.js +37 -0
- package/dist/esm/legacyEnumerationChoices.js.map +1 -0
- package/dist/esm/loadQuill/index.d.ts +3 -0
- package/dist/esm/loadQuill/index.d.ts.map +1 -0
- package/dist/esm/loadQuill/index.js +20 -0
- package/dist/esm/loadQuill/index.js.map +1 -0
- package/dist/esm/primeReactComponents.d.ts.map +1 -1
- package/dist/esm/primeReactComponents.js +15 -0
- package/dist/esm/primeReactComponents.js.map +1 -1
- package/dist/esm/primeReactDescriptors.d.ts +3 -0
- package/dist/esm/primeReactDescriptors.d.ts.map +1 -0
- package/dist/esm/primeReactDescriptors.js +398 -0
- package/dist/esm/primeReactDescriptors.js.map +1 -0
- package/dist/esm/primeReactPackage.d.ts.map +1 -1
- package/dist/esm/primeReactPackage.js +8 -0
- package/dist/esm/primeReactPackage.js.map +1 -1
- package/dist/esm/properties.d.ts +1 -0
- package/dist/esm/properties.d.ts.map +1 -1
- package/dist/esm/properties.js +11 -1
- package/dist/esm/properties.js.map +1 -1
- package/dist/esm/resolveEnumeration.d.ts +3 -0
- package/dist/esm/resolveEnumeration.d.ts.map +1 -0
- package/dist/esm/resolveEnumeration.js +53 -0
- package/dist/esm/resolveEnumeration.js.map +1 -0
- package/dist/esm/structurallyEqual.d.ts +2 -0
- package/dist/esm/structurallyEqual.d.ts.map +1 -0
- package/dist/esm/structurallyEqual.js +25 -0
- package/dist/esm/structurallyEqual.js.map +1 -0
- package/dist/esm/treeNodes.d.ts +2 -1
- package/dist/esm/treeNodes.d.ts.map +1 -1
- package/dist/esm/treeNodes.js +42 -8
- package/dist/esm/treeNodes.js.map +1 -1
- package/dist/esm/tsconfig.tsbuildinfo +1 -1
- package/dist/esm/useResettingState.d.ts +3 -0
- package/dist/esm/useResettingState.d.ts.map +1 -0
- package/dist/esm/useResettingState.js +45 -0
- package/dist/esm/useResettingState.js.map +1 -0
- package/dist/esm/useStructuralValue.d.ts +2 -0
- package/dist/esm/useStructuralValue.d.ts.map +1 -0
- package/dist/esm/useStructuralValue.js +18 -0
- package/dist/esm/useStructuralValue.js.map +1 -0
- package/editor/PrimeEditor.tsx +83 -0
- package/editor/QuillConstructor.ts +8 -0
- package/editor/QuillEditorOptions.ts +29 -0
- package/editor/QuillEditorState.ts +14 -0
- package/editor/QuillInstance.ts +27 -0
- package/editor/QuillLoader.ts +13 -0
- package/editor/QuillLoaderContext.ts +8 -0
- package/editor/QuillLoaderProvider.tsx +24 -0
- package/editor/QuillOptions.ts +10 -0
- package/editor/SafeElement.ts +15 -0
- package/editor/SafeNode.ts +7 -0
- package/editor/applyHtml.ts +21 -0
- package/editor/characterCount.ts +9 -0
- package/editor/htmlToPlainText.ts +74 -0
- package/editor/index.ts +16 -0
- package/editor/renderSafeNodes.tsx +26 -0
- package/editor/safeUrls.ts +43 -0
- package/editor/sanitizeHtml.ts +94 -0
- package/editor/serializeSafeNodes.ts +26 -0
- package/editor/toolbarLayout.ts +10 -0
- package/editor/useQuillEditor.ts +114 -0
- package/file/FileGallery.stories.tsx +32 -0
- package/file/FileUploadContext.ts +17 -0
- package/file/FileUploadHandler.ts +15 -0
- package/file/FileUploadHandlerProvider.tsx +33 -0
- package/file/FileUploadMode.ts +9 -0
- package/file/PrimeFileUpload.tsx +129 -0
- package/file/UploadStatus.ts +9 -0
- package/file/UploadTarget.ts +12 -0
- package/file/index.ts +9 -0
- package/file/postFiles.ts +23 -0
- package/file/resolveUploadTarget.ts +61 -0
- package/file/useUploadSession.ts +67 -0
- package/form/FormGallery.stories.tsx +9 -0
- package/form/MultiStateGlyph.tsx +55 -0
- package/form/MultiStateOption.ts +17 -0
- package/form/PrimeMultiStateCheckbox.tsx +101 -0
- package/form/index.ts +1 -0
- package/form/multiStateOptions.ts +78 -0
- package/form/multiStateStates.ts +23 -0
- package/form/useMultiStateSelection.ts +48 -0
- package/index.ts +4 -0
- package/legacyEnumerationChoices.ts +35 -0
- package/loadQuill/index.ts +21 -0
- package/package.json +27 -7
- package/primeReactComponents.ts +12 -0
- package/primeReactDescriptors.ts +111 -0
- package/primeReactPackage.ts +5 -3
- package/primeReactTheme.css +69 -0
- package/properties.ts +14 -0
- package/resolveEnumeration.ts +50 -0
- package/structurallyEqual.ts +29 -0
- package/treeNodes.ts +44 -6
- package/useResettingState.ts +34 -0
- package/useStructuralValue.ts +17 -0
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
4
|
+
var react = require('react');
|
|
5
|
+
var fileupload = require('primereact/fileupload');
|
|
6
|
+
var properties = require('../properties.js');
|
|
7
|
+
var resolveEnumeration = require('../resolveEnumeration.js');
|
|
8
|
+
var FileUploadContext = require('./FileUploadContext.js');
|
|
9
|
+
var FileUploadMode = require('./FileUploadMode.js');
|
|
10
|
+
var resolveUploadTarget = require('./resolveUploadTarget.js');
|
|
11
|
+
var useUploadSession = require('./useUploadSession.js');
|
|
12
|
+
|
|
13
|
+
const subscribeToNothing = ()=>()=>undefined;
|
|
14
|
+
const pageOrigin = ()=>window.location.origin;
|
|
15
|
+
const noPageOrigin = ()=>undefined;
|
|
16
|
+
/**
|
|
17
|
+
* The `PrimeReact:fileUpload` component.
|
|
18
|
+
*
|
|
19
|
+
* PrimeReact 11 provides the accessible file picker and drop zone; this adapter owns everything that has an
|
|
20
|
+
* effect or a policy:
|
|
21
|
+
* - The authored `url` is untrusted data. It is checked by {@link resolveUploadTarget} - same origin as the
|
|
22
|
+
* page unless the host allows more through {@link FileUploadHandlerProvider} - and a refused address is
|
|
23
|
+
* reported and blocks every upload, the host's handler included.
|
|
24
|
+
* - Nothing is requested on mount. A request starts only when the user selects or drops files (automatic and
|
|
25
|
+
* basic mode) or presses the upload button.
|
|
26
|
+
* - `multiple: false` is enforced before anything is sent, for the file input and for drag and drop.
|
|
27
|
+
* - One upload runs at a time (nothing can be selected or dropped while it runs), and a failure is shown
|
|
28
|
+
* rather than thrown.
|
|
29
|
+
* - A disabled element (`isEnabled: false`) disables the picker, the upload button and the drop zone.
|
|
30
|
+
*
|
|
31
|
+
* Without a host handler the control posts the files itself with `fetch`, sending cookies to the page's own
|
|
32
|
+
* origin only.
|
|
33
|
+
*/ function PrimeFileUpload({ element, interactions }) {
|
|
34
|
+
const { handler, allowedOrigins } = react.useContext(FileUploadContext.FileUploadContext);
|
|
35
|
+
const origin = react.useSyncExternalStore(subscribeToNothing, pageOrigin, noPageOrigin);
|
|
36
|
+
const modeResolution = resolveEnumeration.resolveEnumeration('mode', element.properties.mode, FileUploadMode.FileUploadMode, FileUploadMode.FileUploadMode.Advanced);
|
|
37
|
+
const mode = modeResolution.isValid ? modeResolution.value : FileUploadMode.FileUploadMode.Advanced;
|
|
38
|
+
const authoredUrl = properties.stringProperty(element, 'url');
|
|
39
|
+
const target = react.useMemo(()=>resolveUploadTarget.resolveUploadTarget(authoredUrl, origin, allowedOrigins), [
|
|
40
|
+
authoredUrl,
|
|
41
|
+
origin,
|
|
42
|
+
allowedOrigins
|
|
43
|
+
]);
|
|
44
|
+
const serverUrl = target.isValid ? target.url : undefined;
|
|
45
|
+
const multiple = properties.booleanProperty(element, 'multiple', false);
|
|
46
|
+
const enabled = element.isEnabled;
|
|
47
|
+
const canUpload = target.isValid && (handler !== undefined || serverUrl !== undefined);
|
|
48
|
+
const session = useUploadSession.useUploadSession(handler, serverUrl, properties.stringProperty(element, 'name', 'files'));
|
|
49
|
+
const uploaded = async (event)=>{
|
|
50
|
+
if (!enabled || !canUpload) return;
|
|
51
|
+
if (await session.upload(event.files)) event.options.clear();
|
|
52
|
+
};
|
|
53
|
+
const changed = (event)=>{
|
|
54
|
+
// Clearing the selection after an upload reports an empty change; it is not a new selection, and must not
|
|
55
|
+
// wipe the result of the upload that caused it.
|
|
56
|
+
if (event.acceptedFiles.length === 0 && event.rejectedFiles.length === 0) return;
|
|
57
|
+
const rejection = event.rejectedFiles.flatMap((rejected)=>rejected.errors.map((error)=>error.message)).join(' ');
|
|
58
|
+
session.setStatus(rejection === '' ? undefined : {
|
|
59
|
+
kind: 'error',
|
|
60
|
+
text: rejection
|
|
61
|
+
});
|
|
62
|
+
interactions?.onChange?.();
|
|
63
|
+
};
|
|
64
|
+
const refuseSeveralFromInput = (event)=>{
|
|
65
|
+
const input = event.target;
|
|
66
|
+
if (input.type !== 'file') return;
|
|
67
|
+
if (session.busy) {
|
|
68
|
+
event.stopPropagation();
|
|
69
|
+
input.value = '';
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
if (multiple || (input.files?.length ?? 0) < 2) return;
|
|
73
|
+
event.stopPropagation();
|
|
74
|
+
input.value = '';
|
|
75
|
+
session.setStatus({
|
|
76
|
+
kind: 'error',
|
|
77
|
+
text: 'Only one file can be uploaded at a time.'
|
|
78
|
+
});
|
|
79
|
+
};
|
|
80
|
+
const refuseDrop = (event)=>{
|
|
81
|
+
if (!enabled) {
|
|
82
|
+
event.preventDefault();
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
if (session.busy) {
|
|
86
|
+
event.preventDefault();
|
|
87
|
+
event.stopPropagation();
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
if (multiple || (event.dataTransfer?.files.length ?? 0) < 2) return;
|
|
91
|
+
event.preventDefault();
|
|
92
|
+
event.stopPropagation();
|
|
93
|
+
session.setStatus({
|
|
94
|
+
kind: 'error',
|
|
95
|
+
text: 'Only one file can be uploaded at a time.'
|
|
96
|
+
});
|
|
97
|
+
};
|
|
98
|
+
return /*#__PURE__*/ jsxRuntime.jsx("div", {
|
|
99
|
+
"data-scene-id": element.id,
|
|
100
|
+
"data-scene-component": "fileUpload",
|
|
101
|
+
onClick: interactions?.onClick,
|
|
102
|
+
onDoubleClick: interactions?.onDoubleClick,
|
|
103
|
+
onChangeCapture: refuseSeveralFromInput,
|
|
104
|
+
onDropCapture: refuseDrop,
|
|
105
|
+
onDragOverCapture: (event)=>{
|
|
106
|
+
if (!enabled) event.preventDefault();
|
|
107
|
+
},
|
|
108
|
+
children: /*#__PURE__*/ jsxRuntime.jsx(fileupload.FileUpload.Root, {
|
|
109
|
+
accept: properties.stringProperty(element, 'accept'),
|
|
110
|
+
auto: (mode === FileUploadMode.FileUploadMode.Auto || mode === FileUploadMode.FileUploadMode.Basic) && canUpload,
|
|
111
|
+
customUpload: true,
|
|
112
|
+
disabled: !enabled,
|
|
113
|
+
maxFileSize: properties.numberProperty(element, 'maxFileSize'),
|
|
114
|
+
multiple: multiple,
|
|
115
|
+
name: properties.stringProperty(element, 'name', 'files'),
|
|
116
|
+
uploadHandler: uploaded,
|
|
117
|
+
onChange: changed,
|
|
118
|
+
children: /*#__PURE__*/ jsxRuntime.jsxs(fileupload.FileUpload.Content, {
|
|
119
|
+
"aria-label": properties.stringProperty(element, 'ariaLabel', 'File upload drop zone'),
|
|
120
|
+
children: [
|
|
121
|
+
/*#__PURE__*/ jsxRuntime.jsx("p", {
|
|
122
|
+
children: mode === FileUploadMode.FileUploadMode.Basic ? 'Choose a file to upload.' : 'Drop files here or choose files to upload.'
|
|
123
|
+
}),
|
|
124
|
+
/*#__PURE__*/ jsxRuntime.jsx(fileupload.FileUpload.Trigger, {
|
|
125
|
+
disabled: !enabled || session.busy,
|
|
126
|
+
children: mode === FileUploadMode.FileUploadMode.Basic ? 'Choose file' : 'Choose files'
|
|
127
|
+
}),
|
|
128
|
+
mode === FileUploadMode.FileUploadMode.Advanced && /*#__PURE__*/ jsxRuntime.jsx(fileupload.FileUpload.Upload, {
|
|
129
|
+
disabled: !enabled || !canUpload || session.busy,
|
|
130
|
+
children: "Upload selected files"
|
|
131
|
+
}),
|
|
132
|
+
!modeResolution.isValid && /*#__PURE__*/ jsxRuntime.jsx("p", {
|
|
133
|
+
role: "alert",
|
|
134
|
+
"data-scene-state": "unsupported-mode",
|
|
135
|
+
children: modeResolution.message
|
|
136
|
+
}),
|
|
137
|
+
!target.isValid && /*#__PURE__*/ jsxRuntime.jsx("p", {
|
|
138
|
+
role: "alert",
|
|
139
|
+
"data-scene-state": "refused-address",
|
|
140
|
+
children: target.message
|
|
141
|
+
}),
|
|
142
|
+
target.isValid && !canUpload && /*#__PURE__*/ jsxRuntime.jsx("p", {
|
|
143
|
+
role: "status",
|
|
144
|
+
children: "Configure a server URL or provide an upload handler to upload files."
|
|
145
|
+
}),
|
|
146
|
+
session.busy && /*#__PURE__*/ jsxRuntime.jsx("p", {
|
|
147
|
+
role: "status",
|
|
148
|
+
children: "Uploading…"
|
|
149
|
+
}),
|
|
150
|
+
session.status !== undefined && /*#__PURE__*/ jsxRuntime.jsx("p", {
|
|
151
|
+
role: session.status.kind === 'error' ? 'alert' : 'status',
|
|
152
|
+
children: session.status.text
|
|
153
|
+
})
|
|
154
|
+
]
|
|
155
|
+
})
|
|
156
|
+
})
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
exports.PrimeFileUpload = PrimeFileUpload;
|
|
161
|
+
//# sourceMappingURL=PrimeFileUpload.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PrimeFileUpload.js","sources":["../../../file/PrimeFileUpload.tsx"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { ChangeEvent, DragEvent, useContext, useMemo, useSyncExternalStore } from 'react';\nimport { FileUpload, type FileUploadChangeEvent, type FileUploadHandlerEvent } from 'primereact/fileupload';\nimport { RegisteredComponentProps } from '@cratis/scene.react';\nimport { booleanProperty, numberProperty, stringProperty } from '../properties';\nimport { resolveEnumeration } from '../resolveEnumeration';\nimport { FileUploadContext } from './FileUploadContext';\nimport { FileUploadMode } from './FileUploadMode';\nimport { resolveUploadTarget } from './resolveUploadTarget';\nimport { useUploadSession } from './useUploadSession';\n\nconst subscribeToNothing = () => () => undefined;\nconst pageOrigin = () => window.location.origin;\nconst noPageOrigin = () => undefined;\n\n/**\n * The `PrimeReact:fileUpload` component.\n *\n * PrimeReact 11 provides the accessible file picker and drop zone; this adapter owns everything that has an\n * effect or a policy:\n * - The authored `url` is untrusted data. It is checked by {@link resolveUploadTarget} - same origin as the\n * page unless the host allows more through {@link FileUploadHandlerProvider} - and a refused address is\n * reported and blocks every upload, the host's handler included.\n * - Nothing is requested on mount. A request starts only when the user selects or drops files (automatic and\n * basic mode) or presses the upload button.\n * - `multiple: false` is enforced before anything is sent, for the file input and for drag and drop.\n * - One upload runs at a time (nothing can be selected or dropped while it runs), and a failure is shown\n * rather than thrown.\n * - A disabled element (`isEnabled: false`) disables the picker, the upload button and the drop zone.\n *\n * Without a host handler the control posts the files itself with `fetch`, sending cookies to the page's own\n * origin only.\n */\nexport function PrimeFileUpload({ element, interactions }: RegisteredComponentProps) {\n const { handler, allowedOrigins } = useContext(FileUploadContext);\n const origin = useSyncExternalStore(subscribeToNothing, pageOrigin, noPageOrigin);\n const modeResolution = resolveEnumeration('mode', element.properties.mode, FileUploadMode, FileUploadMode.Advanced);\n const mode = modeResolution.isValid ? modeResolution.value : FileUploadMode.Advanced;\n const authoredUrl = stringProperty(element, 'url');\n const target = useMemo(() => resolveUploadTarget(authoredUrl, origin, allowedOrigins), [authoredUrl, origin, allowedOrigins]);\n const serverUrl = target.isValid ? target.url : undefined;\n const multiple = booleanProperty(element, 'multiple', false);\n const enabled = element.isEnabled;\n const canUpload = target.isValid && (handler !== undefined || serverUrl !== undefined);\n const session = useUploadSession(handler, serverUrl, stringProperty(element, 'name', 'files'));\n\n const uploaded = async (event: FileUploadHandlerEvent) => {\n if (!enabled || !canUpload) return;\n if (await session.upload(event.files)) event.options.clear();\n };\n\n const changed = (event: FileUploadChangeEvent) => {\n // Clearing the selection after an upload reports an empty change; it is not a new selection, and must not\n // wipe the result of the upload that caused it.\n if (event.acceptedFiles.length === 0 && event.rejectedFiles.length === 0) return;\n const rejection = event.rejectedFiles.flatMap(rejected => rejected.errors.map(error => error.message)).join(' ');\n session.setStatus(rejection === '' ? undefined : { kind: 'error', text: rejection });\n interactions?.onChange?.();\n };\n\n const refuseSeveralFromInput = (event: ChangeEvent<HTMLElement>) => {\n const input = event.target as HTMLInputElement;\n if (input.type !== 'file') return;\n if (session.busy) {\n event.stopPropagation();\n input.value = '';\n return;\n }\n\n if (multiple || (input.files?.length ?? 0) < 2) return;\n event.stopPropagation();\n input.value = '';\n session.setStatus({ kind: 'error', text: 'Only one file can be uploaded at a time.' });\n };\n\n const refuseDrop = (event: DragEvent<HTMLElement>) => {\n if (!enabled) {\n event.preventDefault();\n return;\n }\n if (session.busy) {\n event.preventDefault();\n event.stopPropagation();\n return;\n }\n\n if (multiple || (event.dataTransfer?.files.length ?? 0) < 2) return;\n event.preventDefault();\n event.stopPropagation();\n session.setStatus({ kind: 'error', text: 'Only one file can be uploaded at a time.' });\n };\n\n return (\n <div\n data-scene-id={element.id}\n data-scene-component='fileUpload'\n onClick={interactions?.onClick}\n onDoubleClick={interactions?.onDoubleClick}\n onChangeCapture={refuseSeveralFromInput}\n onDropCapture={refuseDrop}\n onDragOverCapture={event => { if (!enabled) event.preventDefault(); }}>\n <FileUpload.Root\n accept={stringProperty(element, 'accept')}\n auto={(mode === FileUploadMode.Auto || mode === FileUploadMode.Basic) && canUpload}\n customUpload\n disabled={!enabled}\n maxFileSize={numberProperty(element, 'maxFileSize')}\n multiple={multiple}\n name={stringProperty(element, 'name', 'files')}\n uploadHandler={uploaded}\n onChange={changed}>\n <FileUpload.Content aria-label={stringProperty(element, 'ariaLabel', 'File upload drop zone')}>\n <p>{mode === FileUploadMode.Basic ? 'Choose a file to upload.' : 'Drop files here or choose files to upload.'}</p>\n <FileUpload.Trigger disabled={!enabled || session.busy}>{mode === FileUploadMode.Basic ? 'Choose file' : 'Choose files'}</FileUpload.Trigger>\n {mode === FileUploadMode.Advanced && (\n <FileUpload.Upload disabled={!enabled || !canUpload || session.busy}>Upload selected files</FileUpload.Upload>\n )}\n {!modeResolution.isValid && <p role='alert' data-scene-state='unsupported-mode'>{modeResolution.message}</p>}\n {!target.isValid && <p role='alert' data-scene-state='refused-address'>{target.message}</p>}\n {target.isValid && !canUpload && <p role='status'>Configure a server URL or provide an upload handler to upload files.</p>}\n {session.busy && <p role='status'>Uploading…</p>}\n {session.status !== undefined && <p role={session.status.kind === 'error' ? 'alert' : 'status'}>{session.status.text}</p>}\n </FileUpload.Content>\n </FileUpload.Root>\n </div>\n );\n}\n"],"names":["subscribeToNothing","undefined","pageOrigin","window","location","origin","noPageOrigin","PrimeFileUpload","element","interactions","handler","allowedOrigins","useContext","FileUploadContext","useSyncExternalStore","modeResolution","resolveEnumeration","properties","mode","FileUploadMode","Advanced","isValid","value","authoredUrl","stringProperty","target","useMemo","resolveUploadTarget","serverUrl","url","multiple","booleanProperty","enabled","isEnabled","canUpload","session","useUploadSession","uploaded","event","upload","files","options","clear","changed","acceptedFiles","length","rejectedFiles","rejection","flatMap","rejected","errors","map","error","message","join","setStatus","kind","text","onChange","refuseSeveralFromInput","input","type","busy","stopPropagation","refuseDrop","preventDefault","dataTransfer","_jsx","div","data-scene-id","id","data-scene-component","onClick","onDoubleClick","onChangeCapture","onDropCapture","onDragOverCapture","FileUpload","Root","accept","auto","Auto","Basic","customUpload","disabled","maxFileSize","numberProperty","name","uploadHandler","_jsxs","Content","aria-label","p","Trigger","Upload","role","data-scene-state","status"],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// Copyright (c) Cratis. All rights reserved.
|
|
4
|
+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
5
|
+
/**
|
|
6
|
+
* Sends files to an address as a `multipart/form-data` POST.
|
|
7
|
+
*
|
|
8
|
+
* Cookies are sent only to the page's own origin (`credentials: 'same-origin'`), so an upload to another
|
|
9
|
+
* origin the host allowed carries no credentials. A redirect fails the upload rather than being followed,
|
|
10
|
+
* because following one would send the files to an address the origin policy never checked.
|
|
11
|
+
*
|
|
12
|
+
* @param url The address, already checked by `resolveUploadTarget`.
|
|
13
|
+
* @param field The multipart field name each file is appended under.
|
|
14
|
+
* @param files The files to send.
|
|
15
|
+
* @param signal Cancels the request.
|
|
16
|
+
* @throws When the request fails or the server does not answer with a success status.
|
|
17
|
+
*/ async function postFiles(url, field, files, signal) {
|
|
18
|
+
const body = new FormData();
|
|
19
|
+
for (const file of files)body.append(field, file, file.name);
|
|
20
|
+
const response = await fetch(url, {
|
|
21
|
+
method: 'POST',
|
|
22
|
+
body,
|
|
23
|
+
credentials: 'same-origin',
|
|
24
|
+
redirect: 'error',
|
|
25
|
+
signal
|
|
26
|
+
});
|
|
27
|
+
if (!response.ok) throw new Error(`The server answered ${response.status}${response.statusText === '' ? '' : ` ${response.statusText}`}.`);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
exports.postFiles = postFiles;
|
|
31
|
+
//# sourceMappingURL=postFiles.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"postFiles.js","sources":["../../../file/postFiles.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\n/**\n * Sends files to an address as a `multipart/form-data` POST.\n *\n * Cookies are sent only to the page's own origin (`credentials: 'same-origin'`), so an upload to another\n * origin the host allowed carries no credentials. A redirect fails the upload rather than being followed,\n * because following one would send the files to an address the origin policy never checked.\n *\n * @param url The address, already checked by `resolveUploadTarget`.\n * @param field The multipart field name each file is appended under.\n * @param files The files to send.\n * @param signal Cancels the request.\n * @throws When the request fails or the server does not answer with a success status.\n */\nexport async function postFiles(url: string, field: string, files: File[], signal: AbortSignal): Promise<void> {\n const body = new FormData();\n for (const file of files) body.append(field, file, file.name);\n\n const response = await fetch(url, { method: 'POST', body, credentials: 'same-origin', redirect: 'error', signal });\n if (!response.ok) throw new Error(`The server answered ${response.status}${response.statusText === '' ? '' : ` ${response.statusText}`}.`);\n}\n"],"names":["postFiles","url","field","files","signal","body","FormData","file","append","name","response","fetch","method","credentials","redirect","ok","Error","status","statusText"],"mappings":";;AAAA;AACA;AAEA;;;;;;;;;;;;IAaO,eAAeA,SAAAA,CAAUC,GAAW,EAAEC,KAAa,EAAEC,KAAa,EAAEC,MAAmB,EAAA;AAC1F,IAAA,MAAMC,OAAO,IAAIC,QAAAA,EAAAA;IACjB,KAAK,MAAMC,QAAQJ,KAAAA,CAAOE,IAAAA,CAAKG,MAAM,CAACN,KAAAA,EAAOK,IAAAA,EAAMA,IAAAA,CAAKE,IAAI,CAAA;IAE5D,MAAMC,QAAAA,GAAW,MAAMC,KAAAA,CAAMV,GAAAA,EAAK;QAAEW,MAAAA,EAAQ,MAAA;AAAQP,QAAAA,IAAAA;QAAMQ,WAAAA,EAAa,aAAA;QAAeC,QAAAA,EAAU,OAAA;AAASV,QAAAA;AAAO,KAAA,CAAA;IAChH,IAAI,CAACM,QAAAA,CAASK,EAAE,EAAE,MAAM,IAAIC,KAAAA,CAAM,CAAC,oBAAoB,EAAEN,QAAAA,CAASO,MAAM,CAAA,EAAGP,SAASQ,UAAU,KAAK,EAAA,GAAK,EAAA,GAAK,CAAC,CAAC,EAAER,QAAAA,CAASQ,UAAU,CAAA,CAAE,CAAC,CAAC,CAAC,CAAA;AAC7I;;"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// Copyright (c) Cratis. All rights reserved.
|
|
4
|
+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
5
|
+
/** A scheme (`https:`) or a protocol-relative prefix (`//host`): the address names its own host. */ const namesItsOwnHost = /^([a-z][a-z0-9+.-]*:|\/\/)/i;
|
|
6
|
+
/** Whitespace, control characters and backslashes, which browsers normalize in ways that disguise another host. */ const disguisesAHost = (address)=>Array.from(address).some((character)=>character <= ' ' || character === '\u007f' || character === '\\');
|
|
7
|
+
/** Resolved against, to read an address's own parts without depending on a page. It is never sent to. */ const placeholderOrigin = 'https://upload-target.invalid';
|
|
8
|
+
/**
|
|
9
|
+
* Checks the address an authored upload sends files to.
|
|
10
|
+
*
|
|
11
|
+
* The address comes from authored model data, so it is not trusted. By default an upload may only go to the
|
|
12
|
+
* origin the page was served from - a relative address, or an absolute one with the same origin. A host that
|
|
13
|
+
* needs another origin names it in `allowedOrigins` when it provides the upload handler. Whatever is accepted
|
|
14
|
+
* has the scheme `http:` or `https:`, carries no user information, and contains no whitespace, control
|
|
15
|
+
* characters or backslashes, because those are how an address is made to point somewhere other than where it
|
|
16
|
+
* reads.
|
|
17
|
+
*
|
|
18
|
+
* @param url The authored address, if any.
|
|
19
|
+
* @param pageOrigin The origin of the page, `undefined` where there is no page (server rendering).
|
|
20
|
+
* @param allowedOrigins The additional origins the host permits.
|
|
21
|
+
* @returns The address to send to, or why it cannot be used.
|
|
22
|
+
*/ function resolveUploadTarget(url, pageOrigin, allowedOrigins) {
|
|
23
|
+
if (url === undefined || url === '') return {
|
|
24
|
+
isValid: true,
|
|
25
|
+
url: undefined
|
|
26
|
+
};
|
|
27
|
+
if (disguisesAHost(url)) return refused('it contains whitespace, control characters or a backslash');
|
|
28
|
+
let resolved;
|
|
29
|
+
try {
|
|
30
|
+
resolved = new URL(url, placeholderOrigin);
|
|
31
|
+
} catch {
|
|
32
|
+
return refused('it is not a valid address');
|
|
33
|
+
}
|
|
34
|
+
if (resolved.protocol !== 'http:' && resolved.protocol !== 'https:') return refused(`the ${resolved.protocol} scheme is not allowed`);
|
|
35
|
+
if (resolved.username !== '' || resolved.password !== '') return refused('it carries user information');
|
|
36
|
+
if (!namesItsOwnHost.test(url)) return {
|
|
37
|
+
isValid: true,
|
|
38
|
+
url
|
|
39
|
+
};
|
|
40
|
+
const permitted = [
|
|
41
|
+
...pageOrigin === undefined ? [] : [
|
|
42
|
+
pageOrigin
|
|
43
|
+
],
|
|
44
|
+
...allowedOrigins.flatMap(originOf)
|
|
45
|
+
];
|
|
46
|
+
return permitted.includes(resolved.origin) ? {
|
|
47
|
+
isValid: true,
|
|
48
|
+
url: resolved.href
|
|
49
|
+
} : refused(`${resolved.origin} is not the origin of this page or one the host allows`);
|
|
50
|
+
}
|
|
51
|
+
function originOf(address) {
|
|
52
|
+
try {
|
|
53
|
+
return [
|
|
54
|
+
new URL(address).origin
|
|
55
|
+
];
|
|
56
|
+
} catch {
|
|
57
|
+
return [];
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
function refused(reason) {
|
|
61
|
+
return {
|
|
62
|
+
isValid: false,
|
|
63
|
+
message: `The upload address is not allowed: ${reason}.`
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
exports.resolveUploadTarget = resolveUploadTarget;
|
|
68
|
+
//# sourceMappingURL=resolveUploadTarget.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolveUploadTarget.js","sources":["../../../file/resolveUploadTarget.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { UploadTarget } from './UploadTarget';\n\n/** A scheme (`https:`) or a protocol-relative prefix (`//host`): the address names its own host. */\nconst namesItsOwnHost = /^([a-z][a-z0-9+.-]*:|\\/\\/)/i;\n\n/** Whitespace, control characters and backslashes, which browsers normalize in ways that disguise another host. */\nconst disguisesAHost = (address: string) => Array.from(address).some(character => character <= ' ' || character === '\\u007f' || character === '\\\\');\n\n/** Resolved against, to read an address's own parts without depending on a page. It is never sent to. */\nconst placeholderOrigin = 'https://upload-target.invalid';\n\n/**\n * Checks the address an authored upload sends files to.\n *\n * The address comes from authored model data, so it is not trusted. By default an upload may only go to the\n * origin the page was served from - a relative address, or an absolute one with the same origin. A host that\n * needs another origin names it in `allowedOrigins` when it provides the upload handler. Whatever is accepted\n * has the scheme `http:` or `https:`, carries no user information, and contains no whitespace, control\n * characters or backslashes, because those are how an address is made to point somewhere other than where it\n * reads.\n *\n * @param url The authored address, if any.\n * @param pageOrigin The origin of the page, `undefined` where there is no page (server rendering).\n * @param allowedOrigins The additional origins the host permits.\n * @returns The address to send to, or why it cannot be used.\n */\nexport function resolveUploadTarget(url: string | undefined, pageOrigin: string | undefined, allowedOrigins: readonly string[]): UploadTarget {\n if (url === undefined || url === '') return { isValid: true, url: undefined };\n if (disguisesAHost(url)) return refused('it contains whitespace, control characters or a backslash');\n\n let resolved: URL;\n try {\n resolved = new URL(url, placeholderOrigin);\n } catch {\n return refused('it is not a valid address');\n }\n\n if (resolved.protocol !== 'http:' && resolved.protocol !== 'https:') return refused(`the ${resolved.protocol} scheme is not allowed`);\n if (resolved.username !== '' || resolved.password !== '') return refused('it carries user information');\n if (!namesItsOwnHost.test(url)) return { isValid: true, url };\n\n const permitted = [...(pageOrigin === undefined ? [] : [pageOrigin]), ...allowedOrigins.flatMap(originOf)];\n return permitted.includes(resolved.origin)\n ? { isValid: true, url: resolved.href }\n : refused(`${resolved.origin} is not the origin of this page or one the host allows`);\n}\n\nfunction originOf(address: string): string[] {\n try {\n return [new URL(address).origin];\n } catch {\n return [];\n }\n}\n\nfunction refused(reason: string): UploadTarget {\n return { isValid: false, message: `The upload address is not allowed: ${reason}.` };\n}\n"],"names":["namesItsOwnHost","disguisesAHost","address","Array","from","some","character","placeholderOrigin","resolveUploadTarget","url","pageOrigin","allowedOrigins","undefined","isValid","refused","resolved","URL","protocol","username","password","test","permitted","flatMap","originOf","includes","origin","href","reason","message"],"mappings":";;AAAA;AACA;AAIA,qGACA,MAAMA,eAAAA,GAAkB,6BAAA;AAExB,oHACA,MAAMC,cAAAA,GAAiB,CAACC,OAAAA,GAAoBC,MAAMC,IAAI,CAACF,OAAAA,CAAAA,CAASG,IAAI,CAACC,CAAAA,SAAAA,GAAaA,aAAa,GAAA,IAAOA,SAAAA,KAAc,YAAYA,SAAAA,KAAc,IAAA,CAAA;AAE9I,0GACA,MAAMC,iBAAAA,GAAoB,+BAAA;AAE1B;;;;;;;;;;;;;;AAcC,IACM,SAASC,mBAAAA,CAAoBC,GAAuB,EAAEC,UAA8B,EAAEC,cAAiC,EAAA;AAC1H,IAAA,IAAIF,GAAAA,KAAQG,SAAAA,IAAaH,GAAAA,KAAQ,EAAA,EAAI,OAAO;QAAEI,OAAAA,EAAS,IAAA;QAAMJ,GAAAA,EAAKG;AAAU,KAAA;IAC5E,IAAIX,cAAAA,CAAeQ,GAAAA,CAAAA,EAAM,OAAOK,OAAAA,CAAQ,2DAAA,CAAA;IAExC,IAAIC,QAAAA;IACJ,IAAI;QACAA,QAAAA,GAAW,IAAIC,IAAIP,GAAAA,EAAKF,iBAAAA,CAAAA;AAC5B,IAAA,CAAA,CAAE,OAAM;AACJ,QAAA,OAAOO,OAAAA,CAAQ,2BAAA,CAAA;AACnB,IAAA;AAEA,IAAA,IAAIC,SAASE,QAAQ,KAAK,OAAA,IAAWF,QAAAA,CAASE,QAAQ,KAAK,QAAA,EAAU,OAAOH,OAAAA,CAAQ,CAAC,IAAI,EAAEC,SAASE,QAAQ,CAAC,sBAAsB,CAAC,CAAA;IACpI,IAAIF,QAAAA,CAASG,QAAQ,KAAK,EAAA,IAAMH,SAASI,QAAQ,KAAK,EAAA,EAAI,OAAOL,OAAAA,CAAQ,6BAAA,CAAA;AACzE,IAAA,IAAI,CAACd,eAAAA,CAAgBoB,IAAI,CAACX,MAAM,OAAO;QAAEI,OAAAA,EAAS,IAAA;AAAMJ,QAAAA;AAAI,KAAA;AAE5D,IAAA,MAAMY,SAAAA,GAAY;WAAKX,UAAAA,KAAeE,SAAAA,GAAY,EAAE,GAAG;AAACF,YAAAA;AAAW,SAAA;AAAMC,QAAAA,GAAAA,cAAAA,CAAeW,OAAO,CAACC,QAAAA;AAAU,KAAA;AAC1G,IAAA,OAAOF,SAAAA,CAAUG,QAAQ,CAACT,QAAAA,CAASU,MAAM,CAAA,GACnC;QAAEZ,OAAAA,EAAS,IAAA;AAAMJ,QAAAA,GAAAA,EAAKM,SAASW;AAAK,KAAA,GACpCZ,QAAQ,CAAA,EAAGC,QAAAA,CAASU,MAAM,CAAC,sDAAsD,CAAC,CAAA;AAC5F;AAEA,SAASF,SAASrB,OAAe,EAAA;IAC7B,IAAI;QACA,OAAO;YAAC,IAAIc,GAAAA,CAAId,SAASuB;AAAO,SAAA;AACpC,IAAA,CAAA,CAAE,OAAM;AACJ,QAAA,OAAO,EAAE;AACb,IAAA;AACJ;AAEA,SAASX,QAAQa,MAAc,EAAA;IAC3B,OAAO;QAAEd,OAAAA,EAAS,KAAA;AAAOe,QAAAA,OAAAA,EAAS,CAAC,mCAAmC,EAAED,MAAAA,CAAO,CAAC;AAAE,KAAA;AACtF;;"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var react = require('react');
|
|
4
|
+
var postFiles = require('./postFiles.js');
|
|
5
|
+
|
|
6
|
+
// Copyright (c) Cratis. All rights reserved.
|
|
7
|
+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
8
|
+
/**
|
|
9
|
+
* Runs one upload at a time for a control, through the host's handler or a POST to the checked address.
|
|
10
|
+
*
|
|
11
|
+
* Starting an upload while one runs is ignored rather than queued, so a double click cannot send the same
|
|
12
|
+
* files twice. Every failure ends in a visible `status`; none escapes as an unhandled rejection. An upload
|
|
13
|
+
* still running when the control unmounts is cancelled.
|
|
14
|
+
*
|
|
15
|
+
* @param handler The host's upload effect, if it owns the effect.
|
|
16
|
+
* @param url The checked address, if one was authored.
|
|
17
|
+
* @param field The multipart field name used when the control posts the files itself.
|
|
18
|
+
*/ function useUploadSession(handler, url, field) {
|
|
19
|
+
const running = react.useRef(undefined);
|
|
20
|
+
const [busy, setBusy] = react.useState(false);
|
|
21
|
+
const [status, setStatus] = react.useState(undefined);
|
|
22
|
+
react.useEffect(()=>()=>running.current?.abort(), []);
|
|
23
|
+
const upload = react.useCallback(async (files)=>{
|
|
24
|
+
if (running.current !== undefined) return false;
|
|
25
|
+
const controller = new AbortController();
|
|
26
|
+
running.current = controller;
|
|
27
|
+
setBusy(true);
|
|
28
|
+
setStatus(undefined);
|
|
29
|
+
try {
|
|
30
|
+
if (handler !== undefined) await handler(files, url);
|
|
31
|
+
else if (url !== undefined) await postFiles.postFiles(url, field, files, controller.signal);
|
|
32
|
+
else throw new Error('There is nowhere to send the files.');
|
|
33
|
+
setStatus({
|
|
34
|
+
kind: 'success',
|
|
35
|
+
text: `${files.length} file${files.length === 1 ? '' : 's'} uploaded.`
|
|
36
|
+
});
|
|
37
|
+
return true;
|
|
38
|
+
} catch (error) {
|
|
39
|
+
if (!controller.signal.aborted) setStatus({
|
|
40
|
+
kind: 'error',
|
|
41
|
+
text: `Upload failed: ${error instanceof Error ? error.message : String(error)}`
|
|
42
|
+
});
|
|
43
|
+
return false;
|
|
44
|
+
} finally{
|
|
45
|
+
running.current = undefined;
|
|
46
|
+
setBusy(false);
|
|
47
|
+
}
|
|
48
|
+
}, [
|
|
49
|
+
handler,
|
|
50
|
+
url,
|
|
51
|
+
field
|
|
52
|
+
]);
|
|
53
|
+
return {
|
|
54
|
+
busy,
|
|
55
|
+
status,
|
|
56
|
+
setStatus,
|
|
57
|
+
upload
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
exports.useUploadSession = useUploadSession;
|
|
62
|
+
//# sourceMappingURL=useUploadSession.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useUploadSession.js","sources":["../../../file/useUploadSession.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport { FileUploadHandler } from './FileUploadHandler';\nimport { UploadStatus } from './UploadStatus';\nimport { postFiles } from './postFiles';\n\n/** The state of the upload in flight, if any, and the action that starts one. */\nexport interface UploadSession {\n /** Whether an upload is running. */\n busy: boolean;\n\n /** The last result, or `undefined` before the first upload and after a new selection. */\n status: UploadStatus | undefined;\n setStatus(status: UploadStatus | undefined): void;\n\n /**\n * Sends the files, unless an upload is already running.\n *\n * @returns Whether the files were sent, so the caller knows to clear its selection. A failure is reported\n * through `status` and returns `false`: the selection stays so it can be retried.\n */\n upload(files: File[]): Promise<boolean>;\n}\n\n/**\n * Runs one upload at a time for a control, through the host's handler or a POST to the checked address.\n *\n * Starting an upload while one runs is ignored rather than queued, so a double click cannot send the same\n * files twice. Every failure ends in a visible `status`; none escapes as an unhandled rejection. An upload\n * still running when the control unmounts is cancelled.\n *\n * @param handler The host's upload effect, if it owns the effect.\n * @param url The checked address, if one was authored.\n * @param field The multipart field name used when the control posts the files itself.\n */\nexport function useUploadSession(handler: FileUploadHandler | undefined, url: string | undefined, field: string): UploadSession {\n const running = useRef<AbortController | undefined>(undefined);\n const [busy, setBusy] = useState(false);\n const [status, setStatus] = useState<UploadStatus | undefined>(undefined);\n\n useEffect(() => () => running.current?.abort(), []);\n\n const upload = useCallback(async (files: File[]): Promise<boolean> => {\n if (running.current !== undefined) return false;\n const controller = new AbortController();\n running.current = controller;\n setBusy(true);\n setStatus(undefined);\n try {\n if (handler !== undefined) await handler(files, url);\n else if (url !== undefined) await postFiles(url, field, files, controller.signal);\n else throw new Error('There is nowhere to send the files.');\n setStatus({ kind: 'success', text: `${files.length} file${files.length === 1 ? '' : 's'} uploaded.` });\n return true;\n } catch (error) {\n if (!controller.signal.aborted) setStatus({ kind: 'error', text: `Upload failed: ${error instanceof Error ? error.message : String(error)}` });\n return false;\n } finally {\n running.current = undefined;\n setBusy(false);\n }\n }, [handler, url, field]);\n\n return { busy, status, setStatus, upload };\n}\n"],"names":["useUploadSession","handler","url","field","running","useRef","undefined","busy","setBusy","useState","status","setStatus","useEffect","current","abort","upload","useCallback","files","controller","AbortController","postFiles","signal","Error","kind","text","length","error","aborted","message","String"],"mappings":";;;;;AAAA;AACA;AAyBA;;;;;;;;;;AAUC,IACM,SAASA,gBAAAA,CAAiBC,OAAsC,EAAEC,GAAuB,EAAEC,KAAa,EAAA;AAC3G,IAAA,MAAMC,UAAUC,YAAAA,CAAoCC,SAAAA,CAAAA;AACpD,IAAA,MAAM,CAACC,IAAAA,EAAMC,OAAAA,CAAQ,GAAGC,cAAAA,CAAS,KAAA,CAAA;AACjC,IAAA,MAAM,CAACC,MAAAA,EAAQC,SAAAA,CAAU,GAAGF,cAAAA,CAAmCH,SAAAA,CAAAA;AAE/DM,IAAAA,eAAAA,CAAU,IAAM,IAAMR,OAAAA,CAAQS,OAAO,EAAEC,SAAS,EAAE,CAAA;IAElD,MAAMC,MAAAA,GAASC,kBAAY,OAAOC,KAAAA,GAAAA;AAC9B,QAAA,IAAIb,OAAAA,CAAQS,OAAO,KAAKP,SAAAA,EAAW,OAAO,KAAA;AAC1C,QAAA,MAAMY,aAAa,IAAIC,eAAAA,EAAAA;AACvBf,QAAAA,OAAAA,CAAQS,OAAO,GAAGK,UAAAA;QAClBV,OAAAA,CAAQ,IAAA,CAAA;QACRG,SAAAA,CAAUL,SAAAA,CAAAA;QACV,IAAI;AACA,YAAA,IAAIL,OAAAA,KAAYK,SAAAA,EAAW,MAAML,OAAAA,CAAQgB,KAAAA,EAAOf,GAAAA,CAAAA;iBAC3C,IAAIA,GAAAA,KAAQI,WAAW,MAAMc,mBAAAA,CAAUlB,KAAKC,KAAAA,EAAOc,KAAAA,EAAOC,WAAWG,MAAM,CAAA;AAC3E,iBAAA,MAAM,IAAIC,KAAAA,CAAM,qCAAA,CAAA;YACrBX,SAAAA,CAAU;gBAAEY,IAAAA,EAAM,SAAA;AAAWC,gBAAAA,IAAAA,EAAM,CAAA,EAAGP,KAAAA,CAAMQ,MAAM,CAAC,KAAK,EAAER,KAAAA,CAAMQ,MAAM,KAAK,CAAA,GAAI,EAAA,GAAK,GAAA,CAAI,UAAU;AAAE,aAAA,CAAA;YACpG,OAAO,IAAA;AACX,QAAA,CAAA,CAAE,OAAOC,KAAAA,EAAO;AACZ,YAAA,IAAI,CAACR,UAAAA,CAAWG,MAAM,CAACM,OAAO,EAAEhB,SAAAA,CAAU;gBAAEY,IAAAA,EAAM,OAAA;gBAASC,IAAAA,EAAM,CAAC,eAAe,EAAEE,KAAAA,YAAiBJ,QAAQI,KAAAA,CAAME,OAAO,GAAGC,MAAAA,CAAOH,KAAAA,CAAAA,CAAAA;AAAS,aAAA,CAAA;YAC5I,OAAO,KAAA;QACX,CAAA,QAAU;AACNtB,YAAAA,OAAAA,CAAQS,OAAO,GAAGP,SAAAA;YAClBE,OAAAA,CAAQ,KAAA,CAAA;AACZ,QAAA;IACJ,CAAA,EAAG;AAACP,QAAAA,OAAAA;AAASC,QAAAA,GAAAA;AAAKC,QAAAA;AAAM,KAAA,CAAA;IAExB,OAAO;AAAEI,QAAAA,IAAAA;AAAMG,QAAAA,MAAAA;AAAQC,QAAAA,SAAAA;AAAWI,QAAAA;AAAO,KAAA;AAC7C;;"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
4
|
+
var scene_react = require('@cratis/scene.react');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* The box a multi-state checkbox draws, themed with the PrimeReact checkbox tokens (`--p-checkbox-*`), so
|
|
8
|
+
* it follows the active Scene theme and looks like its sibling `checkbox`. It holds the state's icon - a
|
|
9
|
+
* PrimeIcons class or a qualified icon reference - or a check mark when the state has no icon of its own.
|
|
10
|
+
* An empty state draws only its own icon, if it has one. It is decorative: the state is announced through the control's text, not through this glyph.
|
|
11
|
+
*/ function MultiStateGlyph({ state, isEmpty, isInactive }) {
|
|
12
|
+
const icon = state?.icon;
|
|
13
|
+
return /*#__PURE__*/ jsxRuntime.jsx("span", {
|
|
14
|
+
"aria-hidden": "true",
|
|
15
|
+
"data-scene-part": "glyph",
|
|
16
|
+
style: {
|
|
17
|
+
display: 'inline-flex',
|
|
18
|
+
alignItems: 'center',
|
|
19
|
+
justifyContent: 'center',
|
|
20
|
+
flexShrink: 0,
|
|
21
|
+
boxSizing: 'border-box',
|
|
22
|
+
width: 'var(--p-checkbox-width, 1.125rem)',
|
|
23
|
+
height: 'var(--p-checkbox-height, 1.125rem)',
|
|
24
|
+
borderRadius: 'var(--p-checkbox-border-radius, 4px)',
|
|
25
|
+
border: `1px solid ${isEmpty ? 'var(--p-checkbox-border-color, currentColor)' : 'var(--p-checkbox-checked-border-color, currentColor)'}`,
|
|
26
|
+
backgroundColor: isEmpty ? 'var(--p-checkbox-background, transparent)' : 'var(--p-checkbox-checked-background, currentColor)',
|
|
27
|
+
color: glyphColor(isEmpty, isInactive),
|
|
28
|
+
fontSize: 'var(--p-checkbox-icon-size, 0.75rem)'
|
|
29
|
+
},
|
|
30
|
+
children: icon === undefined ? !isEmpty && /*#__PURE__*/ jsxRuntime.jsx(CheckMark, {}) : typeof icon === 'string' ? /*#__PURE__*/ jsxRuntime.jsx("i", {
|
|
31
|
+
className: icon
|
|
32
|
+
}) : /*#__PURE__*/ jsxRuntime.jsx(scene_react.SceneIcon, {
|
|
33
|
+
reference: icon,
|
|
34
|
+
size: "var(--p-checkbox-icon-size, 0.75rem)"
|
|
35
|
+
})
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
function glyphColor(isEmpty, isInactive) {
|
|
39
|
+
if (isInactive) return 'var(--p-checkbox-icon-disabled-color, currentColor)';
|
|
40
|
+
return isEmpty ? 'var(--p-checkbox-icon-color, currentColor)' : 'var(--p-checkbox-icon-checked-color, Canvas)';
|
|
41
|
+
}
|
|
42
|
+
function CheckMark() {
|
|
43
|
+
return /*#__PURE__*/ jsxRuntime.jsx("svg", {
|
|
44
|
+
viewBox: "0 0 12 12",
|
|
45
|
+
width: "1em",
|
|
46
|
+
height: "1em",
|
|
47
|
+
fill: "none",
|
|
48
|
+
stroke: "currentColor",
|
|
49
|
+
strokeWidth: "2",
|
|
50
|
+
strokeLinecap: "round",
|
|
51
|
+
strokeLinejoin: "round",
|
|
52
|
+
children: /*#__PURE__*/ jsxRuntime.jsx("path", {
|
|
53
|
+
d: "M2 6.5 5 9.5 10 3"
|
|
54
|
+
})
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
exports.MultiStateGlyph = MultiStateGlyph;
|
|
59
|
+
//# sourceMappingURL=MultiStateGlyph.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MultiStateGlyph.js","sources":["../../../form/MultiStateGlyph.tsx"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { SceneIcon } from '@cratis/scene.react';\nimport { MultiStateOption } from './MultiStateOption';\n\nexport interface MultiStateGlyphProps {\n /** The state being shown. */\n state: MultiStateOption | undefined;\n\n /** Whether the state is the empty (`null`) state, drawn as an empty box. */\n isEmpty: boolean;\n\n /** Whether the control is disabled or read only. */\n isInactive: boolean;\n}\n\n/**\n * The box a multi-state checkbox draws, themed with the PrimeReact checkbox tokens (`--p-checkbox-*`), so\n * it follows the active Scene theme and looks like its sibling `checkbox`. It holds the state's icon - a\n * PrimeIcons class or a qualified icon reference - or a check mark when the state has no icon of its own.\n * An empty state draws only its own icon, if it has one. It is decorative: the state is announced through the control's text, not through this glyph.\n */\nexport function MultiStateGlyph({ state, isEmpty, isInactive }: MultiStateGlyphProps) {\n const icon = state?.icon;\n return (\n <span\n aria-hidden='true'\n data-scene-part='glyph'\n style={{\n display: 'inline-flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0, boxSizing: 'border-box',\n width: 'var(--p-checkbox-width, 1.125rem)', height: 'var(--p-checkbox-height, 1.125rem)',\n borderRadius: 'var(--p-checkbox-border-radius, 4px)',\n border: `1px solid ${isEmpty ? 'var(--p-checkbox-border-color, currentColor)' : 'var(--p-checkbox-checked-border-color, currentColor)'}`,\n backgroundColor: isEmpty ? 'var(--p-checkbox-background, transparent)' : 'var(--p-checkbox-checked-background, currentColor)',\n color: glyphColor(isEmpty, isInactive),\n fontSize: 'var(--p-checkbox-icon-size, 0.75rem)',\n }}>\n {icon === undefined ? !isEmpty && <CheckMark /> : typeof icon === 'string' ? <i className={icon} /> : <SceneIcon reference={icon} size='var(--p-checkbox-icon-size, 0.75rem)' />}\n </span>\n );\n}\n\nfunction glyphColor(isEmpty: boolean, isInactive: boolean): string {\n if (isInactive) return 'var(--p-checkbox-icon-disabled-color, currentColor)';\n return isEmpty ? 'var(--p-checkbox-icon-color, currentColor)' : 'var(--p-checkbox-icon-checked-color, Canvas)';\n}\n\nfunction CheckMark() {\n return (\n <svg viewBox='0 0 12 12' width='1em' height='1em' fill='none' stroke='currentColor' strokeWidth='2' strokeLinecap='round' strokeLinejoin='round'>\n <path d='M2 6.5 5 9.5 10 3' />\n </svg>\n );\n}\n"],"names":["MultiStateGlyph","state","isEmpty","isInactive","icon","_jsx","span","aria-hidden","data-scene-part","style","display","alignItems","justifyContent","flexShrink","boxSizing","width","height","borderRadius","border","backgroundColor","color","glyphColor","fontSize","undefined","CheckMark","i","className","SceneIcon","reference","size","svg","viewBox","fill","stroke","strokeWidth","strokeLinecap","strokeLinejoin","path","d"],"mappings":";;;;;AAiBA;;;;;IAMO,SAASA,eAAAA,CAAgB,EAAEC,KAAK,EAAEC,OAAO,EAAEC,UAAU,EAAwB,EAAA;AAChF,IAAA,MAAMC,OAAOH,KAAAA,EAAOG,IAAAA;AACpB,IAAA,qBACIC,cAAA,CAACC,MAAAA,EAAAA;QACGC,aAAAA,EAAY,MAAA;QACZC,iBAAAA,EAAgB,OAAA;QAChBC,KAAAA,EAAO;YACHC,OAAAA,EAAS,aAAA;YAAeC,UAAAA,EAAY,QAAA;YAAUC,cAAAA,EAAgB,QAAA;YAAUC,UAAAA,EAAY,CAAA;YAAGC,SAAAA,EAAW,YAAA;YAClGC,KAAAA,EAAO,mCAAA;YAAqCC,MAAAA,EAAQ,oCAAA;YACpDC,YAAAA,EAAc,sCAAA;AACdC,YAAAA,MAAAA,EAAQ,CAAC,UAAU,EAAEhB,OAAAA,GAAU,iDAAiD,sDAAA,CAAA,CAAwD;AACxIiB,YAAAA,eAAAA,EAAiBjB,UAAU,2CAAA,GAA8C,oDAAA;AACzEkB,YAAAA,KAAAA,EAAOC,WAAWnB,OAAAA,EAASC,UAAAA,CAAAA;YAC3BmB,QAAAA,EAAU;AACd,SAAA;kBACClB,IAAAA,KAASmB,SAAAA,GAAY,CAACrB,OAAAA,kBAAWG,cAAA,CAACmB,iBAAe,OAAOpB,IAAAA,KAAS,yBAAWC,cAAA,CAACoB,GAAAA,EAAAA;YAAEC,SAAAA,EAAWtB;2BAAWC,cAAA,CAACsB,qBAAAA,EAAAA;YAAUC,SAAAA,EAAWxB,IAAAA;YAAMyB,IAAAA,EAAK;;;AAGnJ;AAEA,SAASR,UAAAA,CAAWnB,OAAgB,EAAEC,UAAmB,EAAA;AACrD,IAAA,IAAIA,YAAY,OAAO,qDAAA;AACvB,IAAA,OAAOD,UAAU,4CAAA,GAA+C,8CAAA;AACpE;AAEA,SAASsB,SAAAA,GAAAA;AACL,IAAA,qBACInB,cAAA,CAACyB,KAAAA,EAAAA;QAAIC,OAAAA,EAAQ,WAAA;QAAYhB,KAAAA,EAAM,KAAA;QAAMC,MAAAA,EAAO,KAAA;QAAMgB,IAAAA,EAAK,MAAA;QAAOC,MAAAA,EAAO,cAAA;QAAeC,WAAAA,EAAY,GAAA;QAAIC,aAAAA,EAAc,OAAA;QAAQC,cAAAA,EAAe,OAAA;AACrI,QAAA,QAAA,gBAAA/B,cAAA,CAACgC,MAAAA,EAAAA;YAAKC,CAAAA,EAAE;;;AAGpB;;"}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
4
|
+
var react = require('react');
|
|
5
|
+
var scene_model = require('@cratis/scene.model');
|
|
6
|
+
var properties = require('../properties.js');
|
|
7
|
+
var MultiStateGlyph = require('./MultiStateGlyph.js');
|
|
8
|
+
var multiStateOptions = require('./multiStateOptions.js');
|
|
9
|
+
var multiStateStates = require('./multiStateStates.js');
|
|
10
|
+
var useMultiStateSelection = require('./useMultiStateSelection.js');
|
|
11
|
+
|
|
12
|
+
const visuallyHidden = {
|
|
13
|
+
position: 'absolute',
|
|
14
|
+
width: 1,
|
|
15
|
+
height: 1,
|
|
16
|
+
margin: -1,
|
|
17
|
+
padding: 0,
|
|
18
|
+
overflow: 'hidden',
|
|
19
|
+
clip: 'rect(0 0 0 0)',
|
|
20
|
+
whiteSpace: 'nowrap',
|
|
21
|
+
border: 0
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* The `PrimeReact:multiStateCheckbox` component.
|
|
25
|
+
*
|
|
26
|
+
* PrimeReact 11 removed MultiStateCheckbox, so Scene renders its original behavior with a native button.
|
|
27
|
+
* It cycles through the authored states in order, including the optional empty (`null`) state, and keeps
|
|
28
|
+
* option values and icons exactly as the element carries them. Each click moves one step; the position is
|
|
29
|
+
* an index, so duplicated or `null` option values do not make later states unreachable.
|
|
30
|
+
*
|
|
31
|
+
* Accessibility: a state cycle is not a true/false choice, so the control does not claim `checkbox`
|
|
32
|
+
* semantics (every non-empty state would announce as "checked"). It is a button whose name is the authored
|
|
33
|
+
* `ariaLabel`, whose description is the current state, and whose state changes are announced through a
|
|
34
|
+
* polite live region. `readOnly` keeps the control focusable and unchanged; `disabled` removes it from the
|
|
35
|
+
* tab order.
|
|
36
|
+
*
|
|
37
|
+
* The control follows the document: a changed `value` or `options` restarts the cycle from the new value,
|
|
38
|
+
* so an inspector edit is reflected immediately. It does not report its own selection to behaviors -
|
|
39
|
+
* Scene's interaction handlers carry no value.
|
|
40
|
+
*/ function PrimeMultiStateCheckbox({ element, interactions }) {
|
|
41
|
+
const stateId = react.useId();
|
|
42
|
+
const allowEmpty = properties.booleanProperty(element, 'empty', true);
|
|
43
|
+
const emptyLabel = properties.stringProperty(element, 'emptyLabel', 'No selection');
|
|
44
|
+
const emptyIcon = element.properties.emptyIcon;
|
|
45
|
+
const states = multiStateStates.multiStateStates(multiStateOptions.multiStateOptions(element, emptyLabel), allowEmpty, emptyLabel, typeof emptyIcon === 'string' || scene_model.isIconReference(emptyIcon) ? emptyIcon : undefined);
|
|
46
|
+
const authored = element.properties.value;
|
|
47
|
+
const { index, advance } = useMultiStateSelection.useMultiStateSelection(states, authored === undefined && allowEmpty ? null : authored);
|
|
48
|
+
const [focused, setFocused] = react.useState(false);
|
|
49
|
+
const selected = states[index];
|
|
50
|
+
const readOnly = properties.booleanProperty(element, 'readOnly', false);
|
|
51
|
+
const disabled = !element.isEnabled || properties.booleanProperty(element, 'disabled', false) || states.length === 0;
|
|
52
|
+
const ariaLabel = properties.stringProperty(element, 'ariaLabel', element.name || 'Multi-state checkbox');
|
|
53
|
+
const stateText = selected?.label ?? properties.stringProperty(element, 'placeholder', unmatchedText(states.length, authored, emptyLabel));
|
|
54
|
+
return /*#__PURE__*/ jsxRuntime.jsxs(jsxRuntime.Fragment, {
|
|
55
|
+
children: [
|
|
56
|
+
/*#__PURE__*/ jsxRuntime.jsxs("button", {
|
|
57
|
+
type: "button",
|
|
58
|
+
"data-scene-id": element.id,
|
|
59
|
+
"data-scene-component": "multiStateCheckbox",
|
|
60
|
+
"data-scene-state-index": index,
|
|
61
|
+
"aria-label": ariaLabel,
|
|
62
|
+
"aria-describedby": stateId,
|
|
63
|
+
"aria-disabled": readOnly ? true : undefined,
|
|
64
|
+
disabled: disabled,
|
|
65
|
+
style: {
|
|
66
|
+
display: 'inline-flex',
|
|
67
|
+
alignItems: 'center',
|
|
68
|
+
gap: '0.5rem',
|
|
69
|
+
padding: 0,
|
|
70
|
+
border: 0,
|
|
71
|
+
background: 'none',
|
|
72
|
+
font: 'inherit',
|
|
73
|
+
color: 'inherit',
|
|
74
|
+
cursor: disabled ? 'not-allowed' : readOnly ? 'default' : 'pointer',
|
|
75
|
+
opacity: disabled ? 0.6 : 1,
|
|
76
|
+
outline: focused ? 'var(--p-focus-ring-width, 2px) var(--p-focus-ring-style, solid) var(--p-focus-ring-color, currentColor)' : 'none',
|
|
77
|
+
outlineOffset: 'var(--p-focus-ring-offset, 2px)'
|
|
78
|
+
},
|
|
79
|
+
onFocus: (event)=>setFocused(isFocusVisible(event.currentTarget)),
|
|
80
|
+
onBlur: ()=>setFocused(false),
|
|
81
|
+
onClick: (event)=>{
|
|
82
|
+
if (!readOnly) advance();
|
|
83
|
+
interactions?.onClick?.(event);
|
|
84
|
+
if (readOnly) return;
|
|
85
|
+
interactions?.onChange?.();
|
|
86
|
+
interactions?.onSelect?.();
|
|
87
|
+
},
|
|
88
|
+
onDoubleClick: interactions?.onDoubleClick,
|
|
89
|
+
children: [
|
|
90
|
+
/*#__PURE__*/ jsxRuntime.jsx(MultiStateGlyph.MultiStateGlyph, {
|
|
91
|
+
state: selected,
|
|
92
|
+
isEmpty: selected === undefined || selected.value === null,
|
|
93
|
+
isInactive: disabled || readOnly
|
|
94
|
+
}),
|
|
95
|
+
/*#__PURE__*/ jsxRuntime.jsx("span", {
|
|
96
|
+
"aria-hidden": "true",
|
|
97
|
+
children: stateText
|
|
98
|
+
})
|
|
99
|
+
]
|
|
100
|
+
}),
|
|
101
|
+
/*#__PURE__*/ jsxRuntime.jsx("span", {
|
|
102
|
+
id: stateId,
|
|
103
|
+
role: "status",
|
|
104
|
+
style: visuallyHidden,
|
|
105
|
+
children: stateText
|
|
106
|
+
})
|
|
107
|
+
]
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
function unmatchedText(stateCount, authored, emptyLabel) {
|
|
111
|
+
if (stateCount === 0) return 'No states';
|
|
112
|
+
return authored === undefined ? emptyLabel : 'No matching state';
|
|
113
|
+
}
|
|
114
|
+
function isFocusVisible(target) {
|
|
115
|
+
try {
|
|
116
|
+
return target.matches(':focus-visible');
|
|
117
|
+
} catch {
|
|
118
|
+
return true;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
exports.PrimeMultiStateCheckbox = PrimeMultiStateCheckbox;
|
|
123
|
+
//# sourceMappingURL=PrimeMultiStateCheckbox.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PrimeMultiStateCheckbox.js","sources":["../../../form/PrimeMultiStateCheckbox.tsx"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { CSSProperties, useId, useState } from 'react';\nimport { isIconReference } from '@cratis/scene.model';\nimport { RegisteredComponentProps } from '@cratis/scene.react';\nimport { booleanProperty, stringProperty } from '../properties';\nimport { MultiStateGlyph } from './MultiStateGlyph';\nimport { multiStateOptions } from './multiStateOptions';\nimport { multiStateStates } from './multiStateStates';\nimport { useMultiStateSelection } from './useMultiStateSelection';\n\nconst visuallyHidden: CSSProperties = {\n position: 'absolute', width: 1, height: 1, margin: -1, padding: 0, overflow: 'hidden', clip: 'rect(0 0 0 0)', whiteSpace: 'nowrap', border: 0,\n};\n\n/**\n * The `PrimeReact:multiStateCheckbox` component.\n *\n * PrimeReact 11 removed MultiStateCheckbox, so Scene renders its original behavior with a native button.\n * It cycles through the authored states in order, including the optional empty (`null`) state, and keeps\n * option values and icons exactly as the element carries them. Each click moves one step; the position is\n * an index, so duplicated or `null` option values do not make later states unreachable.\n *\n * Accessibility: a state cycle is not a true/false choice, so the control does not claim `checkbox`\n * semantics (every non-empty state would announce as \"checked\"). It is a button whose name is the authored\n * `ariaLabel`, whose description is the current state, and whose state changes are announced through a\n * polite live region. `readOnly` keeps the control focusable and unchanged; `disabled` removes it from the\n * tab order.\n *\n * The control follows the document: a changed `value` or `options` restarts the cycle from the new value,\n * so an inspector edit is reflected immediately. It does not report its own selection to behaviors -\n * Scene's interaction handlers carry no value.\n */\nexport function PrimeMultiStateCheckbox({ element, interactions }: RegisteredComponentProps) {\n const stateId = useId();\n const allowEmpty = booleanProperty(element, 'empty', true);\n const emptyLabel = stringProperty(element, 'emptyLabel', 'No selection');\n const emptyIcon = element.properties.emptyIcon;\n const states = multiStateStates(\n multiStateOptions(element, emptyLabel),\n allowEmpty,\n emptyLabel,\n typeof emptyIcon === 'string' || isIconReference(emptyIcon) ? emptyIcon : undefined);\n const authored = element.properties.value;\n const { index, advance } = useMultiStateSelection(states, authored === undefined && allowEmpty ? null : authored);\n const [focused, setFocused] = useState(false);\n\n const selected = states[index];\n const readOnly = booleanProperty(element, 'readOnly', false);\n const disabled = !element.isEnabled || booleanProperty(element, 'disabled', false) || states.length === 0;\n const ariaLabel = stringProperty(element, 'ariaLabel', element.name || 'Multi-state checkbox');\n const stateText = selected?.label ?? stringProperty(element, 'placeholder', unmatchedText(states.length, authored, emptyLabel));\n\n return (\n <>\n <button\n type='button'\n data-scene-id={element.id}\n data-scene-component='multiStateCheckbox'\n data-scene-state-index={index}\n aria-label={ariaLabel}\n aria-describedby={stateId}\n aria-disabled={readOnly ? true : undefined}\n disabled={disabled}\n style={{\n display: 'inline-flex', alignItems: 'center', gap: '0.5rem', padding: 0, border: 0, background: 'none', font: 'inherit',\n color: 'inherit', cursor: disabled ? 'not-allowed' : readOnly ? 'default' : 'pointer', opacity: disabled ? 0.6 : 1,\n outline: focused ? 'var(--p-focus-ring-width, 2px) var(--p-focus-ring-style, solid) var(--p-focus-ring-color, currentColor)' : 'none',\n outlineOffset: 'var(--p-focus-ring-offset, 2px)',\n }}\n onFocus={(event) => setFocused(isFocusVisible(event.currentTarget))}\n onBlur={() => setFocused(false)}\n onClick={(event) => {\n if (!readOnly) advance();\n interactions?.onClick?.(event);\n if (readOnly) return;\n interactions?.onChange?.();\n interactions?.onSelect?.();\n }}\n onDoubleClick={interactions?.onDoubleClick}>\n <MultiStateGlyph state={selected} isEmpty={selected === undefined || selected.value === null} isInactive={disabled || readOnly} />\n <span aria-hidden='true'>{stateText}</span>\n </button>\n <span id={stateId} role='status' style={visuallyHidden}>{stateText}</span>\n </>\n );\n}\n\nfunction unmatchedText(stateCount: number, authored: unknown, emptyLabel: string): string {\n if (stateCount === 0) return 'No states';\n return authored === undefined ? emptyLabel : 'No matching state';\n}\n\nfunction isFocusVisible(target: HTMLElement): boolean {\n try {\n return target.matches(':focus-visible');\n } catch {\n return true;\n }\n}\n"],"names":["visuallyHidden","position","width","height","margin","padding","overflow","clip","whiteSpace","border","PrimeMultiStateCheckbox","element","interactions","stateId","useId","allowEmpty","booleanProperty","emptyLabel","stringProperty","emptyIcon","properties","states","multiStateStates","multiStateOptions","isIconReference","undefined","authored","value","index","advance","useMultiStateSelection","focused","setFocused","useState","selected","readOnly","disabled","isEnabled","length","ariaLabel","name","stateText","label","unmatchedText","_jsxs","_Fragment","button","type","data-scene-id","id","data-scene-component","data-scene-state-index","aria-label","aria-describedby","aria-disabled","style","display","alignItems","gap","background","font","color","cursor","opacity","outline","outlineOffset","onFocus","event","isFocusVisible","currentTarget","onBlur","onClick","onChange","onSelect","onDoubleClick","_jsx","MultiStateGlyph","state","isEmpty","isInactive","span","aria-hidden","role","stateCount","target","matches"],"mappings":"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"}
|