@smwb/ui-react 2.2.0 → 2.3.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/dist/assets/styles/less/components/appBar/appBar.entry.css +1 -1
- package/dist/assets/styles/less/components/assetGrid/assetGrid.entry.css +1 -0
- package/dist/assets/styles/less/components/chipGroup/chipGroup.entry.css +1 -0
- package/dist/assets/styles/less/components/lazyImage/lazyImage.entry.css +1 -0
- package/dist/assets/styles/less/components/overflowMenu/overflowMenu.entry.css +1 -0
- package/dist/assets/styles/less/components/saveAssetDialog/saveAssetDialog.entry.css +1 -0
- package/dist/assets/styles/less/components/sheet/sheet.entry.css +1 -1
- package/dist/assets/styles/less/components/thumbCard/thumbCard.entry.css +1 -0
- package/dist/assets/styles/less/components/valueSlider/valueSlider.entry.css +1 -0
- package/dist/components/dataDisplay/assetGrid/assetGrid.d.ts +30 -0
- package/dist/components/dataDisplay/assetGrid/assetGrid.js +68 -0
- package/dist/components/dataDisplay/assetGrid/assetGrid.js.map +1 -0
- package/dist/components/dataDisplay/assetGrid/index.d.ts +2 -0
- package/dist/components/dataDisplay/chipGroup/chipGroup.d.ts +27 -0
- package/dist/components/dataDisplay/chipGroup/chipGroup.js +42 -0
- package/dist/components/dataDisplay/chipGroup/chipGroup.js.map +1 -0
- package/dist/components/dataDisplay/chipGroup/index.d.ts +2 -0
- package/dist/components/dataDisplay/lazyImage/index.d.ts +2 -0
- package/dist/components/dataDisplay/lazyImage/lazyImage.d.ts +22 -0
- package/dist/components/dataDisplay/lazyImage/lazyImage.js +52 -0
- package/dist/components/dataDisplay/lazyImage/lazyImage.js.map +1 -0
- package/dist/components/dataDisplay/thumbCard/index.d.ts +2 -0
- package/dist/components/dataDisplay/thumbCard/thumbCard.d.ts +29 -0
- package/dist/components/dataDisplay/thumbCard/thumbCard.js +82 -0
- package/dist/components/dataDisplay/thumbCard/thumbCard.js.map +1 -0
- package/dist/components/feedBack/saveAssetDialog/index.d.ts +2 -0
- package/dist/components/feedBack/saveAssetDialog/saveAssetDialog.d.ts +30 -0
- package/dist/components/feedBack/saveAssetDialog/saveAssetDialog.js +60 -0
- package/dist/components/feedBack/saveAssetDialog/saveAssetDialog.js.map +1 -0
- package/dist/components/inputs/valueSlider/index.d.ts +2 -0
- package/dist/components/inputs/valueSlider/valueSlider.d.ts +23 -0
- package/dist/components/inputs/valueSlider/valueSlider.js +55 -0
- package/dist/components/inputs/valueSlider/valueSlider.js.map +1 -0
- package/dist/components/navigation/overflowMenu/index.d.ts +2 -0
- package/dist/components/navigation/overflowMenu/overflowMenu.d.ts +27 -0
- package/dist/components/navigation/overflowMenu/overflowMenu.js +54 -0
- package/dist/components/navigation/overflowMenu/overflowMenu.js.map +1 -0
- package/dist/headless/components/dataDisplay/assetGrid/assetGrid.js +67 -0
- package/dist/headless/components/dataDisplay/assetGrid/assetGrid.js.map +1 -0
- package/dist/headless/components/dataDisplay/chipGroup/chipGroup.js +41 -0
- package/dist/headless/components/dataDisplay/chipGroup/chipGroup.js.map +1 -0
- package/dist/headless/components/dataDisplay/lazyImage/lazyImage.js +51 -0
- package/dist/headless/components/dataDisplay/lazyImage/lazyImage.js.map +1 -0
- package/dist/headless/components/dataDisplay/thumbCard/thumbCard.js +81 -0
- package/dist/headless/components/dataDisplay/thumbCard/thumbCard.js.map +1 -0
- package/dist/headless/components/feedBack/saveAssetDialog/saveAssetDialog.js +59 -0
- package/dist/headless/components/feedBack/saveAssetDialog/saveAssetDialog.js.map +1 -0
- package/dist/headless/components/inputs/valueSlider/valueSlider.js +54 -0
- package/dist/headless/components/inputs/valueSlider/valueSlider.js.map +1 -0
- package/dist/headless/components/navigation/overflowMenu/overflowMenu.js +53 -0
- package/dist/headless/components/navigation/overflowMenu/overflowMenu.js.map +1 -0
- package/dist/headless/index.js +240 -226
- package/dist/headless/index.js.map +1 -1
- package/dist/index.cjs +2 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +14 -0
- package/dist/index.js +240 -226
- package/dist/index.js.map +1 -1
- package/package.json +6 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
.smwb-appbar{padding:0 16px;display:flex;align-items:center;inset:0 0 auto;min-width:100%;background-color:var(--smui-appBarBg);color:var(--smui-appBarContentColor);font-size:1rem;height:65px}.smwb-appbar.smwb-bottom{bottom:0;top:auto}.smwb-appbar.smwb-relative{position:relative}.smwb-appbar.smwb-static{position:static}.smwb-appbar.smwb-sticky{position:sticky}.smwb-appbar.smwb-fixed{position:fixed}.smwb-appbar.smwb-absolute{position:absolute}.smwb-appbar.smwb-dense{padding:12px;height:48px}.smwb-appbar__inner{display:flex;align-items:center;width:100%;justify-content:space-between;flex-wrap:nowrap}.smwb-appbar__left{display:flex;align-items:center;gap:10px;white-space:nowrap}.smwb-appbar__right{white-space:nowrap}.smwb-appbar__mid{width:100%;display:flex;flex:1 1 auto;flex-direction:column;flex-wrap:nowrap}.smwb-appbar__mid.smwb-middle{align-items:center}.smwb-appbar__mid.smwb-right{align-items:flex-end}.smwb-appbar__mid.smwb-left{align-items:flex-start}.smwb-appbar_color-primary{background-color:var(--smui-primaryColor);color:var(--smui-onPrimaryColor)}.smwb-appbar_color-secondary{background-color:var(--smui-secondaryColor);color:var(--smui-onSecondaryColor)}.smwb-appbar_color-error{background-color:var(--smui-errorColor);color:var(--smui-onErrorColor)}.smwb-appbar_color-success{background-color:var(--smui-successColor);color:var(--smui-onSuccessColor)}.smwb-appbar_color-warning{background-color:var(--smui-warningColor);color:var(--smui-onWarningColor)}.smwb-appbar_color-info{background-color:var(--smui-infoColor);color:var(--smui-onInfoColor)}
|
|
1
|
+
.smwb-appbar{box-sizing:border-box;padding:0 16px;display:flex;align-items:center;inset:0 0 auto;min-width:100%;background-color:var(--smui-appBarBg);color:var(--smui-appBarContentColor);font-size:1rem;height:65px}.smwb-appbar.smwb-bottom{bottom:0;top:auto}.smwb-appbar.smwb-relative{position:relative}.smwb-appbar.smwb-static{position:static}.smwb-appbar.smwb-sticky{position:sticky}.smwb-appbar.smwb-fixed{position:fixed}.smwb-appbar.smwb-absolute{position:absolute}.smwb-appbar.smwb-dense{padding:12px;height:48px}.smwb-appbar__inner{display:flex;align-items:center;width:100%;justify-content:space-between;flex-wrap:nowrap}.smwb-appbar__left{display:flex;align-items:center;gap:10px;white-space:nowrap}.smwb-appbar__right{white-space:nowrap}.smwb-appbar__mid{width:100%;display:flex;flex:1 1 auto;flex-direction:column;flex-wrap:nowrap}.smwb-appbar__mid.smwb-middle{align-items:center}.smwb-appbar__mid.smwb-right{align-items:flex-end}.smwb-appbar__mid.smwb-left{align-items:flex-start}.smwb-appbar_color-primary{background-color:var(--smui-primaryColor);color:var(--smui-onPrimaryColor)}.smwb-appbar_color-secondary{background-color:var(--smui-secondaryColor);color:var(--smui-onSecondaryColor)}.smwb-appbar_color-error{background-color:var(--smui-errorColor);color:var(--smui-onErrorColor)}.smwb-appbar_color-success{background-color:var(--smui-successColor);color:var(--smui-onSuccessColor)}.smwb-appbar_color-warning{background-color:var(--smui-warningColor);color:var(--smui-onWarningColor)}.smwb-appbar_color-info{background-color:var(--smui-infoColor);color:var(--smui-onInfoColor)}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.smwb-asset-grid{position:relative;overflow-y:auto;width:100%}.smwb-asset-grid__empty{display:flex;align-items:center;justify-content:center;padding:32px 16px;color:var(--smui-onSurfaceColor);opacity:.7}.smwb-asset-grid__skeleton{border-radius:8px;background-color:var(--smui-surfaceVariant);animation:smwb-asset-grid-pulse 1.4s ease-in-out infinite}@keyframes smwb-asset-grid-pulse{0%,to{opacity:1}50%{opacity:.5}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.smwb-chip-group{display:flex;flex-wrap:wrap;align-items:center;gap:8px}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.smwb-lazy-image{display:block;position:relative;overflow:hidden;width:100%;height:100%}.smwb-lazy-image__img{display:block;width:100%;height:100%;object-fit:cover}.smwb-lazy-image__fallback{display:flex;align-items:center;justify-content:center;width:100%;height:100%;color:var(--smui-onSurfaceColor);background-color:var(--smui-surfaceVariant)}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.smwb-overflow-menu{display:inline-flex}.smwb-overflow-menu__item--danger{color:var(--smui-errorColor)}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.smwb-save-asset-dialog__body{display:flex;flex-direction:column;gap:12px;min-width:280px}.smwb-save-asset-dialog__preview{display:flex;justify-content:center;align-items:center;border-radius:8px;overflow:hidden;background-color:var(--smui-surfaceVariant)}.smwb-save-asset-dialog__preview img{max-width:100%;max-height:200px;object-fit:contain}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
.smwb-sheet{background-color:var(--smui-surfaceBackground);position:fixed;opacity:0;transition:all .2s ease-in-out;box-shadow:#00000024 0 8px 10px -5px,#00000024 0 1px 14px 1px,#00000024 0 6px 22px 4px;z-index:100;padding:10px 20px 20px;overflow:hidden;display:flex;max-width:100vw}.smwb-sheet__header{display:flex;justify-content:space-between;align-items:center;flex-shrink:0;gap:4px;padding-bottom:5px}.smwb-sheet__header .smwb-button{min-width:0}.smwb-sheet__drag-handle{position:absolute;display:flex;align-items:center;justify-content:center;z-index:1;touch-action:none;user-select:none}.smwb-sheet__drag-handle:focus-visible{outline:2px solid var(--smui-primaryColor);outline-offset:-2px}.smwb-sheet__drag-handle-bar{display:block;border-radius:999px;background-color:var(--smui-onSurfaceVariant);opacity:.4;transition:opacity .15s ease-in-out}.smwb-sheet__drag-handle:hover .smwb-sheet__drag-handle-bar,.smwb-sheet__drag-handle:active .smwb-sheet__drag-handle-bar{opacity:.7}.smwb-sheet_resizable.smwb-bottom{padding-top:20px}.smwb-sheet_resizable.smwb-top{padding-bottom:20px}.smwb-sheet_resizable.smwb-left{padding-right:20px}.smwb-sheet_resizable.smwb-right{padding-left:20px}.smwb-sheet.smwb-bottom .smwb-sheet__drag-handle,.smwb-sheet.smwb-top .smwb-sheet__drag-handle{left:0;right:0;height:20px;cursor:ns-resize}.smwb-sheet.smwb-bottom .smwb-sheet__drag-handle .smwb-sheet__drag-handle-bar,.smwb-sheet.smwb-top .smwb-sheet__drag-handle .smwb-sheet__drag-handle-bar{width:36px;height:4px}.smwb-sheet.smwb-bottom .smwb-sheet__drag-handle{top:0}.smwb-sheet.smwb-top .smwb-sheet__drag-handle{bottom:0}.smwb-sheet.smwb-left .smwb-sheet__drag-handle,.smwb-sheet.smwb-right .smwb-sheet__drag-handle{top:0;bottom:0;width:20px;cursor:ew-resize}.smwb-sheet.smwb-left .smwb-sheet__drag-handle .smwb-sheet__drag-handle-bar,.smwb-sheet.smwb-right .smwb-sheet__drag-handle .smwb-sheet__drag-handle-bar{width:4px;height:36px}.smwb-sheet.smwb-right .smwb-sheet__drag-handle{left:0}.smwb-sheet.smwb-left .smwb-sheet__drag-handle{right:0}.smwb-sheet__inner{display:flex;flex-direction:column;height:100%;width:100%;overflow-y:auto}.smwb-sheet.smwb-bottom{border-radius:28px 28px 0 0;bottom:0;left:0;width:100%;height:var(--sizeProp);transform:translateY(100%);flex-direction:column}.smwb-sheet.smwb-bottom .smwb-sheet__header{width:100%}.smwb-sheet.smwb-top{border-radius:0 0 28px 28px;top:0;left:0;width:100%;height:var(--sizeProp);transform:translateY(-100%);flex-direction:column}.smwb-sheet.smwb-top .smwb-sheet__header{width:100%}.smwb-sheet.smwb-left{border-radius:0 28px 28px 0;top:0;left:0;height:100%;width:var(--sizeProp);transform:translate(-100%);flex-direction:row-reverse}.smwb-sheet.smwb-left .smwb-sheet__header{flex-direction:column;height:100%;padding-left:10px}.smwb-sheet.smwb-right{border-radius:28px 0 0 28px;top:0;right:0;height:100%;width:var(--sizeProp);transform:translate(100%)}.smwb-sheet.smwb-right .smwb-sheet__header{flex-direction:column;height:100%}.smwb-sheet__overlay{position:fixed;top:0;left:0;width:100%;height:100%;display:flex;flex-direction:column;z-index:100;opacity:0;transition:all .25s ease-in-out}.smwb-sheet__overlay.smwb-entered{opacity:1}.smwb-sheet__overlay.smwb-dark{background-color:#00000080}.smwb-sheet__default.smwb-entered .smwb-sheet,.smwb-sheet__overlay.smwb-entered .smwb-sheet{opacity:1}.smwb-sheet__default.smwb-entered .smwb-sheet.smwb-bottom,.smwb-sheet__overlay.smwb-entered .smwb-sheet.smwb-bottom{transform:translateY(0)}.smwb-sheet__default.smwb-entered .smwb-sheet.smwb-bottom.smwb-expanded,.smwb-sheet__overlay.smwb-entered .smwb-sheet.smwb-bottom.smwb-expanded{height:90%}.smwb-sheet__default.smwb-entered .smwb-sheet.smwb-bottom.smwb-small,.smwb-sheet__overlay.smwb-entered .smwb-sheet.smwb-bottom.smwb-small{height:10%}.smwb-sheet__default.smwb-entered .smwb-sheet.smwb-top,.smwb-sheet__overlay.smwb-entered .smwb-sheet.smwb-top{transform:translateY(0)}.smwb-sheet__default.smwb-entered .smwb-sheet.smwb-top.smwb-expanded,.smwb-sheet__overlay.smwb-entered .smwb-sheet.smwb-top.smwb-expanded{height:90%}.smwb-sheet__default.smwb-entered .smwb-sheet.smwb-top.smwb-small,.smwb-sheet__overlay.smwb-entered .smwb-sheet.smwb-top.smwb-small{height:10%}.smwb-sheet__default.smwb-entered .smwb-sheet.smwb-left,.smwb-sheet__overlay.smwb-entered .smwb-sheet.smwb-left{transform:translate(0)}.smwb-sheet__default.smwb-entered .smwb-sheet.smwb-left.smwb-expanded,.smwb-sheet__overlay.smwb-entered .smwb-sheet.smwb-left.smwb-expanded{width:90%}.smwb-sheet__default.smwb-entered .smwb-sheet.smwb-left.smwb-small,.smwb-sheet__overlay.smwb-entered .smwb-sheet.smwb-left.smwb-small{width:10%}.smwb-sheet__default.smwb-entered .smwb-sheet.smwb-right,.smwb-sheet__overlay.smwb-entered .smwb-sheet.smwb-right{transform:translate(0)}.smwb-sheet__default.smwb-entered .smwb-sheet.smwb-right.smwb-expanded,.smwb-sheet__overlay.smwb-entered .smwb-sheet.smwb-right.smwb-expanded{width:90%}.smwb-sheet__default.smwb-entered .smwb-sheet.smwb-right.smwb-small,.smwb-sheet__overlay.smwb-entered .smwb-sheet.smwb-right.smwb-small{width:10%}.smwb-scrollbar::-webkit-scrollbar-thumb{background-color:var(--smui-scrollThumbColor);width:6px;border-radius:999px}.smwb-scrollbar::-webkit-scrollbar{width:6px}.smwb-scrollbar::-webkit-scrollbar-track{background-color:transparent}
|
|
1
|
+
.smwb-sheet{background-color:var(--smui-surfaceBackground);position:fixed;opacity:0;transition:all .2s ease-in-out;box-shadow:#00000024 0 8px 10px -5px,#00000024 0 1px 14px 1px,#00000024 0 6px 22px 4px;z-index:100;padding:10px 20px 20px;box-sizing:border-box;overflow:hidden;display:flex;max-width:100vw}.smwb-sheet__header{display:flex;justify-content:space-between;align-items:center;flex-shrink:0;gap:4px;padding-bottom:5px}.smwb-sheet__header .smwb-button{min-width:0}.smwb-sheet__drag-handle{position:absolute;display:flex;align-items:center;justify-content:center;z-index:1;touch-action:none;user-select:none}.smwb-sheet__drag-handle:focus-visible{outline:2px solid var(--smui-primaryColor);outline-offset:-2px}.smwb-sheet__drag-handle-bar{display:block;border-radius:999px;background-color:var(--smui-onSurfaceVariant);opacity:.4;transition:opacity .15s ease-in-out}.smwb-sheet__drag-handle:hover .smwb-sheet__drag-handle-bar,.smwb-sheet__drag-handle:active .smwb-sheet__drag-handle-bar{opacity:.7}.smwb-sheet_resizable.smwb-bottom{padding-top:20px}.smwb-sheet_resizable.smwb-top{padding-bottom:20px}.smwb-sheet_resizable.smwb-left{padding-right:20px}.smwb-sheet_resizable.smwb-right{padding-left:20px}.smwb-sheet.smwb-bottom .smwb-sheet__drag-handle,.smwb-sheet.smwb-top .smwb-sheet__drag-handle{left:0;right:0;height:20px;cursor:ns-resize}.smwb-sheet.smwb-bottom .smwb-sheet__drag-handle .smwb-sheet__drag-handle-bar,.smwb-sheet.smwb-top .smwb-sheet__drag-handle .smwb-sheet__drag-handle-bar{width:36px;height:4px}.smwb-sheet.smwb-bottom .smwb-sheet__drag-handle{top:0}.smwb-sheet.smwb-top .smwb-sheet__drag-handle{bottom:0}.smwb-sheet.smwb-left .smwb-sheet__drag-handle,.smwb-sheet.smwb-right .smwb-sheet__drag-handle{top:0;bottom:0;width:20px;cursor:ew-resize}.smwb-sheet.smwb-left .smwb-sheet__drag-handle .smwb-sheet__drag-handle-bar,.smwb-sheet.smwb-right .smwb-sheet__drag-handle .smwb-sheet__drag-handle-bar{width:4px;height:36px}.smwb-sheet.smwb-right .smwb-sheet__drag-handle{left:0}.smwb-sheet.smwb-left .smwb-sheet__drag-handle{right:0}.smwb-sheet__inner{display:flex;flex-direction:column;height:100%;width:100%;overflow-y:auto}.smwb-sheet.smwb-bottom{border-radius:28px 28px 0 0;bottom:0;left:0;width:100%;height:var(--sizeProp);transform:translateY(100%);flex-direction:column}.smwb-sheet.smwb-bottom .smwb-sheet__header{width:100%}.smwb-sheet.smwb-top{border-radius:0 0 28px 28px;top:0;left:0;width:100%;height:var(--sizeProp);transform:translateY(-100%);flex-direction:column}.smwb-sheet.smwb-top .smwb-sheet__header{width:100%}.smwb-sheet.smwb-left{border-radius:0 28px 28px 0;top:0;left:0;height:100%;width:var(--sizeProp);transform:translate(-100%);flex-direction:row-reverse}.smwb-sheet.smwb-left .smwb-sheet__header{flex-direction:column;height:100%;padding-left:10px}.smwb-sheet.smwb-right{border-radius:28px 0 0 28px;top:0;right:0;height:100%;width:var(--sizeProp);transform:translate(100%)}.smwb-sheet.smwb-right .smwb-sheet__header{flex-direction:column;height:100%}.smwb-sheet__overlay{position:fixed;top:0;left:0;width:100%;height:100%;display:flex;flex-direction:column;z-index:100;opacity:0;transition:all .25s ease-in-out}.smwb-sheet__overlay.smwb-entered{opacity:1}.smwb-sheet__overlay.smwb-dark{background-color:#00000080}.smwb-sheet__default.smwb-entered .smwb-sheet,.smwb-sheet__overlay.smwb-entered .smwb-sheet{opacity:1}.smwb-sheet__default.smwb-entered .smwb-sheet.smwb-bottom,.smwb-sheet__overlay.smwb-entered .smwb-sheet.smwb-bottom{transform:translateY(0)}.smwb-sheet__default.smwb-entered .smwb-sheet.smwb-bottom.smwb-expanded,.smwb-sheet__overlay.smwb-entered .smwb-sheet.smwb-bottom.smwb-expanded{height:90%}.smwb-sheet__default.smwb-entered .smwb-sheet.smwb-bottom.smwb-small,.smwb-sheet__overlay.smwb-entered .smwb-sheet.smwb-bottom.smwb-small{height:10%}.smwb-sheet__default.smwb-entered .smwb-sheet.smwb-top,.smwb-sheet__overlay.smwb-entered .smwb-sheet.smwb-top{transform:translateY(0)}.smwb-sheet__default.smwb-entered .smwb-sheet.smwb-top.smwb-expanded,.smwb-sheet__overlay.smwb-entered .smwb-sheet.smwb-top.smwb-expanded{height:90%}.smwb-sheet__default.smwb-entered .smwb-sheet.smwb-top.smwb-small,.smwb-sheet__overlay.smwb-entered .smwb-sheet.smwb-top.smwb-small{height:10%}.smwb-sheet__default.smwb-entered .smwb-sheet.smwb-left,.smwb-sheet__overlay.smwb-entered .smwb-sheet.smwb-left{transform:translate(0)}.smwb-sheet__default.smwb-entered .smwb-sheet.smwb-left.smwb-expanded,.smwb-sheet__overlay.smwb-entered .smwb-sheet.smwb-left.smwb-expanded{width:90%}.smwb-sheet__default.smwb-entered .smwb-sheet.smwb-left.smwb-small,.smwb-sheet__overlay.smwb-entered .smwb-sheet.smwb-left.smwb-small{width:10%}.smwb-sheet__default.smwb-entered .smwb-sheet.smwb-right,.smwb-sheet__overlay.smwb-entered .smwb-sheet.smwb-right{transform:translate(0)}.smwb-sheet__default.smwb-entered .smwb-sheet.smwb-right.smwb-expanded,.smwb-sheet__overlay.smwb-entered .smwb-sheet.smwb-right.smwb-expanded{width:90%}.smwb-sheet__default.smwb-entered .smwb-sheet.smwb-right.smwb-small,.smwb-sheet__overlay.smwb-entered .smwb-sheet.smwb-right.smwb-small{width:10%}.smwb-scrollbar::-webkit-scrollbar-thumb{background-color:var(--smui-scrollThumbColor);width:6px;border-radius:999px}.smwb-scrollbar::-webkit-scrollbar{width:6px}.smwb-scrollbar::-webkit-scrollbar-track{background-color:transparent}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.smwb-thumb-card{position:relative;display:flex;flex-direction:column;border-radius:8px;overflow:visible;outline:none}.smwb-thumb-card--interactive{cursor:pointer}.smwb-thumb-card--disabled{opacity:.5;pointer-events:none}.smwb-thumb-card__media{position:relative;width:100%;aspect-ratio:1;border-radius:8px;overflow:hidden;background-color:var(--smui-surfaceVariant)}.smwb-thumb-card--selected .smwb-thumb-card__media{outline:2px solid var(--smui-primaryColor);outline-offset:1px}.smwb-thumb-card--interactive:focus-visible .smwb-thumb-card__media{outline:2px solid var(--smui-primaryColor);outline-offset:1px}.smwb-thumb-card__slot{position:absolute;top:4px;display:flex;gap:4px;z-index:1}.smwb-thumb-card__slot--start{left:4px}.smwb-thumb-card__slot--end{right:4px}.smwb-thumb-card__caption{margin-top:4px;font-size:.8125rem;color:var(--smui-onSurfaceColor);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.smwb-thumb-card__preview{z-index:1000;border-radius:8px;overflow:hidden;box-shadow:0 8px 24px #0000004d;background-color:var(--smui-surfaceBackground);pointer-events:none}.smwb-thumb-card__preview img{display:block;max-width:320px;max-height:320px;object-fit:contain}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.smwb-value-slider{display:flex;flex-direction:column;width:100%}.smwb-value-slider__header{display:flex;align-items:center;gap:8px;min-height:24px}.smwb-value-slider__label{font-size:.875rem;color:var(--smui-onSurfaceColor)}.smwb-value-slider__spacer{flex:1 1 auto}.smwb-value-slider__readout{font-size:.875rem;font-variant-numeric:tabular-nums;color:var(--smui-onSurfaceColor);opacity:.85}.smwb-value-slider__reset{display:inline-flex;align-items:center;justify-content:center;padding:2px;border:none;background:transparent;color:var(--smui-onSurfaceColor);cursor:pointer;border-radius:50%;opacity:.7}.smwb-value-slider__reset:hover{opacity:1;background-color:var(--smui-onSurfaceHover)}.smwb-value-slider__reset:disabled{opacity:.4;cursor:default}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
export interface AssetGridProps<T> {
|
|
3
|
+
items: T[];
|
|
4
|
+
/** Render one cell. `index` is the absolute index into `items`. */
|
|
5
|
+
renderItem: (item: T, index: number) => React.ReactNode;
|
|
6
|
+
/** Minimum column width (px); drives the column count from the measured width. Default 160. */
|
|
7
|
+
minColumn?: number;
|
|
8
|
+
/** Fixed cell height (px). */
|
|
9
|
+
rowHeight: number;
|
|
10
|
+
/** Gap (px) between cells on both axes. Default 8. */
|
|
11
|
+
gap?: number;
|
|
12
|
+
/** Extra rows rendered above/below the viewport. Default 2. */
|
|
13
|
+
overscan?: number;
|
|
14
|
+
loading?: boolean;
|
|
15
|
+
/** Skeleton tile count while loading. Default 12. */
|
|
16
|
+
loadingCount?: number;
|
|
17
|
+
emptyLabel?: React.ReactNode;
|
|
18
|
+
className?: string;
|
|
19
|
+
style?: React.CSSProperties;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* A virtualized, data-shape-agnostic asset grid: measures its own width to pick a
|
|
23
|
+
* column count, windows rows via `useVirtualList`, and renders only the visible
|
|
24
|
+
* cells through a `renderItem` slot — with loading skeletons + an empty state. The
|
|
25
|
+
* windowing math every catalog app reimplements, upstreamed. SSR-safe: before it
|
|
26
|
+
* can measure (server + first paint) it renders a plain auto-fill grid of all
|
|
27
|
+
* items, then virtualizes after mount.
|
|
28
|
+
*/
|
|
29
|
+
export declare function AssetGrid<T>({ items, renderItem, minColumn, rowHeight, gap, overscan, loading, loadingCount, emptyLabel, className, style, }: AssetGridProps<T>): React.ReactElement;
|
|
30
|
+
export default AssetGrid;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { jsx as e } from "react/jsx-runtime";
|
|
2
|
+
import '../../../assets/styles/less/components/assetGrid/assetGrid.entry.css';/* empty css */
|
|
3
|
+
import _, { useRef as H, useState as h, useEffect as I, useMemo as O } from "react";
|
|
4
|
+
import T from "clsx";
|
|
5
|
+
import { useVirtualList as W } from "../../../hooks/useVirtualList.js";
|
|
6
|
+
function L({
|
|
7
|
+
items: l,
|
|
8
|
+
renderItem: f,
|
|
9
|
+
minColumn: d = 160,
|
|
10
|
+
rowHeight: a,
|
|
11
|
+
gap: r = 8,
|
|
12
|
+
overscan: v = 2,
|
|
13
|
+
loading: b,
|
|
14
|
+
loadingCount: w = 12,
|
|
15
|
+
emptyLabel: x,
|
|
16
|
+
className: N,
|
|
17
|
+
style: R
|
|
18
|
+
}) {
|
|
19
|
+
const g = H(null), [c, A] = h(0), [M, S] = h(0), [z, $] = h(!1);
|
|
20
|
+
I(() => {
|
|
21
|
+
const s = g.current;
|
|
22
|
+
if (!s || typeof ResizeObserver == "undefined") return;
|
|
23
|
+
const t = new ResizeObserver(() => {
|
|
24
|
+
A(s.clientWidth), S(s.clientHeight), $(!0);
|
|
25
|
+
});
|
|
26
|
+
return t.observe(s), () => t.disconnect();
|
|
27
|
+
}, []);
|
|
28
|
+
const o = O(
|
|
29
|
+
() => c <= 0 ? 1 : Math.max(1, Math.floor((c + r) / (d + r))),
|
|
30
|
+
[c, r, d]
|
|
31
|
+
), C = Math.ceil(l.length / o), i = W({
|
|
32
|
+
itemCount: C,
|
|
33
|
+
itemHeight: a + r,
|
|
34
|
+
viewportHeight: M || 1,
|
|
35
|
+
overscan: v
|
|
36
|
+
}), u = {
|
|
37
|
+
display: "grid",
|
|
38
|
+
gridTemplateColumns: `repeat(auto-fill, minmax(${d}px, 1fr))`,
|
|
39
|
+
gap: r,
|
|
40
|
+
gridAutoRows: a
|
|
41
|
+
}, F = {
|
|
42
|
+
display: "grid",
|
|
43
|
+
gridTemplateColumns: `repeat(${o}, minmax(0, 1fr))`,
|
|
44
|
+
gap: r,
|
|
45
|
+
height: a,
|
|
46
|
+
marginBottom: r
|
|
47
|
+
};
|
|
48
|
+
let n;
|
|
49
|
+
return b ? n = /* @__PURE__ */ e("div", { className: "smwb-asset-grid__plain", style: u, children: Array.from({ length: w }).map((s, t) => /* @__PURE__ */ e("div", { className: "smwb-asset-grid__skeleton", style: { height: a } }, t)) }) : l.length === 0 ? n = /* @__PURE__ */ e("div", { className: "smwb-asset-grid__empty", children: x }) : z ? n = /* @__PURE__ */ e("div", { className: "smwb-asset-grid__sizer", style: { height: i.totalHeight, position: "relative" }, children: /* @__PURE__ */ e(
|
|
50
|
+
"div",
|
|
51
|
+
{
|
|
52
|
+
className: "smwb-asset-grid__band",
|
|
53
|
+
style: { position: "absolute", top: 0, left: 0, right: 0, transform: `translateY(${i.offsetY}px)` },
|
|
54
|
+
children: Array.from({ length: Math.max(0, i.endIndex - i.startIndex) }).map((s, t) => {
|
|
55
|
+
const p = i.startIndex + t;
|
|
56
|
+
return /* @__PURE__ */ e("div", { className: "smwb-asset-grid__row", style: F, children: Array.from({ length: o }).map((Y, y) => {
|
|
57
|
+
const m = p * o + y;
|
|
58
|
+
return m < l.length ? /* @__PURE__ */ e(_.Fragment, { children: f(l[m], m) }, y) : null;
|
|
59
|
+
}) }, p);
|
|
60
|
+
})
|
|
61
|
+
}
|
|
62
|
+
) }) : n = /* @__PURE__ */ e("div", { className: "smwb-asset-grid__plain", style: u, children: l.map((s, t) => /* @__PURE__ */ e(_.Fragment, { children: f(s, t) }, t)) }), /* @__PURE__ */ e("div", { ref: g, className: T("smwb-asset-grid", N), style: R, onScroll: i.onScroll, children: n });
|
|
63
|
+
}
|
|
64
|
+
export {
|
|
65
|
+
L as AssetGrid,
|
|
66
|
+
L as default
|
|
67
|
+
};
|
|
68
|
+
//# sourceMappingURL=assetGrid.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"assetGrid.js","sources":["../../../../src/components/dataDisplay/assetGrid/assetGrid.tsx"],"sourcesContent":["import React, { useEffect, useMemo, useRef, useState } from \"react\";\nimport cn from \"clsx\";\nimport { useVirtualList } from \"../../../hooks/useVirtualList\";\n\nexport interface AssetGridProps<T> {\n items: T[];\n /** Render one cell. `index` is the absolute index into `items`. */\n renderItem: (item: T, index: number) => React.ReactNode;\n /** Minimum column width (px); drives the column count from the measured width. Default 160. */\n minColumn?: number;\n /** Fixed cell height (px). */\n rowHeight: number;\n /** Gap (px) between cells on both axes. Default 8. */\n gap?: number;\n /** Extra rows rendered above/below the viewport. Default 2. */\n overscan?: number;\n loading?: boolean;\n /** Skeleton tile count while loading. Default 12. */\n loadingCount?: number;\n emptyLabel?: React.ReactNode;\n className?: string;\n style?: React.CSSProperties;\n}\n\n/**\n * A virtualized, data-shape-agnostic asset grid: measures its own width to pick a\n * column count, windows rows via `useVirtualList`, and renders only the visible\n * cells through a `renderItem` slot — with loading skeletons + an empty state. The\n * windowing math every catalog app reimplements, upstreamed. SSR-safe: before it\n * can measure (server + first paint) it renders a plain auto-fill grid of all\n * items, then virtualizes after mount.\n */\nexport function AssetGrid<T>({\n items,\n renderItem,\n minColumn = 160,\n rowHeight,\n gap = 8,\n overscan = 2,\n loading,\n loadingCount = 12,\n emptyLabel,\n className,\n style,\n}: AssetGridProps<T>): React.ReactElement {\n const viewportRef = useRef<HTMLDivElement | null>(null);\n const [width, setWidth] = useState(0);\n const [height, setHeight] = useState(0);\n const [ready, setReady] = useState(false);\n\n useEffect(() => {\n const el = viewportRef.current;\n if (!el || typeof ResizeObserver === \"undefined\") return;\n const ro = new ResizeObserver(() => {\n setWidth(el.clientWidth);\n setHeight(el.clientHeight);\n setReady(true);\n });\n ro.observe(el);\n return () => ro.disconnect();\n }, []);\n\n const cols = useMemo(\n () => (width <= 0 ? 1 : Math.max(1, Math.floor((width + gap) / (minColumn + gap)))),\n [width, gap, minColumn]\n );\n const rowCount = Math.ceil(items.length / cols);\n const vl = useVirtualList({\n itemCount: rowCount,\n itemHeight: rowHeight + gap,\n viewportHeight: height || 1,\n overscan,\n });\n\n const plainStyle: React.CSSProperties = {\n display: \"grid\",\n gridTemplateColumns: `repeat(auto-fill, minmax(${minColumn}px, 1fr))`,\n gap,\n gridAutoRows: rowHeight,\n };\n const rowStyle: React.CSSProperties = {\n display: \"grid\",\n gridTemplateColumns: `repeat(${cols}, minmax(0, 1fr))`,\n gap,\n height: rowHeight,\n marginBottom: gap,\n };\n\n let body: React.ReactNode;\n if (loading) {\n body = (\n <div className=\"smwb-asset-grid__plain\" style={plainStyle}>\n {Array.from({ length: loadingCount }).map((_, i) => (\n <div key={i} className=\"smwb-asset-grid__skeleton\" style={{ height: rowHeight }} />\n ))}\n </div>\n );\n } else if (items.length === 0) {\n body = <div className=\"smwb-asset-grid__empty\">{emptyLabel}</div>;\n } else if (!ready) {\n body = (\n <div className=\"smwb-asset-grid__plain\" style={plainStyle}>\n {items.map((item, index) => (\n <React.Fragment key={index}>{renderItem(item, index)}</React.Fragment>\n ))}\n </div>\n );\n } else {\n body = (\n <div className=\"smwb-asset-grid__sizer\" style={{ height: vl.totalHeight, position: \"relative\" }}>\n <div\n className=\"smwb-asset-grid__band\"\n style={{ position: \"absolute\", top: 0, left: 0, right: 0, transform: `translateY(${vl.offsetY}px)` }}\n >\n {Array.from({ length: Math.max(0, vl.endIndex - vl.startIndex) }).map((_, r) => {\n const row = vl.startIndex + r;\n return (\n <div key={row} className=\"smwb-asset-grid__row\" style={rowStyle}>\n {Array.from({ length: cols }).map((_, c) => {\n const index = row * cols + c;\n return index < items.length ? (\n <React.Fragment key={c}>{renderItem(items[index], index)}</React.Fragment>\n ) : null;\n })}\n </div>\n );\n })}\n </div>\n </div>\n );\n }\n\n return (\n <div ref={viewportRef} className={cn(\"smwb-asset-grid\", className)} style={style} onScroll={vl.onScroll}>\n {body}\n </div>\n );\n}\n\nexport default AssetGrid;\n"],"names":["AssetGrid","items","renderItem","minColumn","rowHeight","gap","overscan","loading","loadingCount","emptyLabel","className","style","viewportRef","useRef","width","setWidth","useState","height","setHeight","ready","setReady","useEffect","el","ro","cols","useMemo","rowCount","vl","useVirtualList","plainStyle","rowStyle","body","jsx","_","i","r","row","c","index","React","item","cn"],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { type ChipColor } from "../chip";
|
|
3
|
+
export interface ChipGroupOption {
|
|
4
|
+
value: string;
|
|
5
|
+
label: string;
|
|
6
|
+
icon?: React.ReactNode;
|
|
7
|
+
disabled?: boolean;
|
|
8
|
+
}
|
|
9
|
+
export interface ChipGroupProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "onChange"> {
|
|
10
|
+
options: ChipGroupOption[];
|
|
11
|
+
/** Selected value (single) or values (when `multiple`). */
|
|
12
|
+
value?: string | string[];
|
|
13
|
+
/** Allow more than one selected chip (value becomes a string[]). */
|
|
14
|
+
multiple?: boolean;
|
|
15
|
+
onChange?: (value: string | string[]) => void;
|
|
16
|
+
size?: "small" | "medium";
|
|
17
|
+
color?: ChipColor;
|
|
18
|
+
disabled?: boolean;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* A multi/single-select toggle group built on `Chip` — the "chip as a toggle"
|
|
22
|
+
* loop (selected → filled, else outlined; `role=group`) apps re-hand-roll for
|
|
23
|
+
* filters / segmented controls. Pass an `options` array and a controlled
|
|
24
|
+
* `value`; `onChange` returns the next value (string, or string[] when multiple).
|
|
25
|
+
*/
|
|
26
|
+
export declare function ChipGroup({ options, value, multiple, onChange, size, color, disabled, className, ...rest }: ChipGroupProps): React.ReactElement;
|
|
27
|
+
export default ChipGroup;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { jsx as u } from "react/jsx-runtime";
|
|
2
|
+
import '../../../assets/styles/less/components/chipGroup/chipGroup.entry.css';/* empty css */
|
|
3
|
+
import A from "clsx";
|
|
4
|
+
import { Chip as j } from "../chip/chip.js";
|
|
5
|
+
function S({
|
|
6
|
+
options: d,
|
|
7
|
+
value: e,
|
|
8
|
+
multiple: t,
|
|
9
|
+
onChange: l,
|
|
10
|
+
size: m = "medium",
|
|
11
|
+
color: f = "primary",
|
|
12
|
+
disabled: a,
|
|
13
|
+
className: b,
|
|
14
|
+
...p
|
|
15
|
+
}) {
|
|
16
|
+
const c = () => e == null ? [] : Array.isArray(e) ? e : [e], i = (r) => c().includes(r), v = (r) => {
|
|
17
|
+
if (t) {
|
|
18
|
+
const s = c(), x = s.includes(r) ? s.filter((y) => y !== r) : [...s, r];
|
|
19
|
+
l == null || l(x);
|
|
20
|
+
} else
|
|
21
|
+
l == null || l(r);
|
|
22
|
+
};
|
|
23
|
+
return /* @__PURE__ */ u("div", { ...p, role: "group", className: A("smwb-chip-group", b), children: d.map((r) => /* @__PURE__ */ u(
|
|
24
|
+
j,
|
|
25
|
+
{
|
|
26
|
+
label: r.label,
|
|
27
|
+
icon: r.icon,
|
|
28
|
+
size: m,
|
|
29
|
+
color: f,
|
|
30
|
+
selected: i(r.value),
|
|
31
|
+
variant: i(r.value) ? "filled" : "outlined",
|
|
32
|
+
disabled: !!(a || r.disabled),
|
|
33
|
+
onClick: () => v(r.value)
|
|
34
|
+
},
|
|
35
|
+
r.value
|
|
36
|
+
)) });
|
|
37
|
+
}
|
|
38
|
+
export {
|
|
39
|
+
S as ChipGroup,
|
|
40
|
+
S as default
|
|
41
|
+
};
|
|
42
|
+
//# sourceMappingURL=chipGroup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chipGroup.js","sources":["../../../../src/components/dataDisplay/chipGroup/chipGroup.tsx"],"sourcesContent":["import React from \"react\";\nimport cn from \"clsx\";\nimport { Chip, type ChipColor } from \"../chip\";\n\nexport interface ChipGroupOption {\n value: string;\n label: string;\n icon?: React.ReactNode;\n disabled?: boolean;\n}\n\nexport interface ChipGroupProps extends Omit<React.HTMLAttributes<HTMLDivElement>, \"onChange\"> {\n options: ChipGroupOption[];\n /** Selected value (single) or values (when `multiple`). */\n value?: string | string[];\n /** Allow more than one selected chip (value becomes a string[]). */\n multiple?: boolean;\n onChange?: (value: string | string[]) => void;\n size?: \"small\" | \"medium\";\n color?: ChipColor;\n disabled?: boolean;\n}\n\n/**\n * A multi/single-select toggle group built on `Chip` — the \"chip as a toggle\"\n * loop (selected → filled, else outlined; `role=group`) apps re-hand-roll for\n * filters / segmented controls. Pass an `options` array and a controlled\n * `value`; `onChange` returns the next value (string, or string[] when multiple).\n */\nexport function ChipGroup({\n options,\n value,\n multiple,\n onChange,\n size = \"medium\",\n color = \"primary\",\n disabled,\n className,\n ...rest\n}: ChipGroupProps): React.ReactElement {\n const selectedValues = (): string[] => {\n if (value == null) return [];\n return Array.isArray(value) ? value : [value];\n };\n const isSelected = (option: string): boolean => selectedValues().includes(option);\n\n const toggle = (option: string): void => {\n if (multiple) {\n const current = selectedValues();\n const next = current.includes(option) ? current.filter((v) => v !== option) : [...current, option];\n onChange?.(next);\n } else {\n onChange?.(option);\n }\n };\n\n return (\n <div {...rest} role=\"group\" className={cn(\"smwb-chip-group\", className)}>\n {options.map((option) => (\n <Chip\n key={option.value}\n label={option.label}\n icon={option.icon}\n size={size}\n color={color}\n selected={isSelected(option.value)}\n variant={isSelected(option.value) ? \"filled\" : \"outlined\"}\n disabled={!!(disabled || option.disabled)}\n onClick={() => toggle(option.value)}\n />\n ))}\n </div>\n );\n}\n\nexport default ChipGroup;\n"],"names":["ChipGroup","options","value","multiple","onChange","size","color","disabled","className","rest","selectedValues","isSelected","option","toggle","current","next","v","jsx","cn","Chip"],"mappings":";;;;AA8BO,SAASA,EAAU;AAAA,EACxB,SAAAC;AAAA,EACA,OAAAC;AAAA,EACA,UAAAC;AAAA,EACA,UAAAC;AAAA,EACA,MAAAC,IAAO;AAAA,EACP,OAAAC,IAAQ;AAAA,EACR,UAAAC;AAAA,EACA,WAAAC;AAAA,EACA,GAAGC;AACL,GAAuC;AACrC,QAAMC,IAAiB,MACjBR,KAAS,OAAa,CAAA,IACnB,MAAM,QAAQA,CAAK,IAAIA,IAAQ,CAACA,CAAK,GAExCS,IAAa,CAACC,MAA4BF,EAAA,EAAiB,SAASE,CAAM,GAE1EC,IAAS,CAACD,MAAyB;AACvC,QAAIT,GAAU;AACZ,YAAMW,IAAUJ,EAAA,GACVK,IAAOD,EAAQ,SAASF,CAAM,IAAIE,EAAQ,OAAO,CAACE,MAAMA,MAAMJ,CAAM,IAAI,CAAC,GAAGE,GAASF,CAAM;AACjG,MAAAR,KAAA,QAAAA,EAAWW;AAAA,IACb;AACE,MAAAX,KAAA,QAAAA,EAAWQ;AAAA,EAEf;AAEA,SACE,gBAAAK,EAAC,OAAA,EAAK,GAAGR,GAAM,MAAK,SAAQ,WAAWS,EAAG,mBAAmBV,CAAS,GACnE,UAAAP,EAAQ,IAAI,CAACW,MACZ,gBAAAK;AAAA,IAACE;AAAA,IAAA;AAAA,MAEC,OAAOP,EAAO;AAAA,MACd,MAAMA,EAAO;AAAA,MACb,MAAAP;AAAA,MACA,OAAAC;AAAA,MACA,UAAUK,EAAWC,EAAO,KAAK;AAAA,MACjC,SAASD,EAAWC,EAAO,KAAK,IAAI,WAAW;AAAA,MAC/C,UAAU,CAAC,EAAEL,KAAYK,EAAO;AAAA,MAChC,SAAS,MAAMC,EAAOD,EAAO,KAAK;AAAA,IAAA;AAAA,IAR7BA,EAAO;AAAA,EAAA,CAUf,GACH;AAEJ;"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
export interface LazyImageProps extends Omit<React.ImgHTMLAttributes<HTMLImageElement>, "onError"> {
|
|
3
|
+
/** Image URL. When absent (or after a load error) the `fallback` is shown. */
|
|
4
|
+
src?: string | undefined;
|
|
5
|
+
alt?: string | undefined;
|
|
6
|
+
/** Rendered in place of the image when it is missing or fails to load. */
|
|
7
|
+
fallback?: React.ReactNode;
|
|
8
|
+
/** Defer loading until the image scrolls into view (IntersectionObserver). Default true. */
|
|
9
|
+
lazy?: boolean;
|
|
10
|
+
/** CSS `aspect-ratio` for the wrapper (e.g. `1`, `"4 / 3"`) to reserve space before load. */
|
|
11
|
+
aspectRatio?: string | number;
|
|
12
|
+
/** Fires on a load error (after the fallback is swapped in). */
|
|
13
|
+
onError?: (event: React.SyntheticEvent<HTMLImageElement>) => void;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* An `<img>` with a built-in `onError` fallback and optional in-viewport lazy
|
|
17
|
+
* loading — the `<img decoding=async onError=…>` + fallback dance hand-rolled in
|
|
18
|
+
* every gallery, in one primitive. SSR-safe: renders the image markup on the
|
|
19
|
+
* server; the IntersectionObserver only runs in an effect on the client.
|
|
20
|
+
*/
|
|
21
|
+
export declare const LazyImage: React.ForwardRefExoticComponent<LazyImageProps & React.RefAttributes<HTMLImageElement>>;
|
|
22
|
+
export default LazyImage;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { jsxs as z, jsx as u } from "react/jsx-runtime";
|
|
2
|
+
import '../../../assets/styles/less/components/lazyImage/lazyImage.entry.css';/* empty css */
|
|
3
|
+
import { forwardRef as _, useState as d, useRef as x, useEffect as F } from "react";
|
|
4
|
+
import N from "clsx";
|
|
5
|
+
import { useForkRef as j } from "../../../hooks/useForkRef.js";
|
|
6
|
+
const A = _(function({ src: c, alt: t, fallback: a, lazy: e = !0, aspectRatio: m, className: g, onError: n, ...b }, p) {
|
|
7
|
+
const [y, v] = d(!1), [i, l] = d(!e), f = x(null), w = j(p, f);
|
|
8
|
+
F(() => {
|
|
9
|
+
if (!e || i) return;
|
|
10
|
+
const s = f.current;
|
|
11
|
+
if (!s) return;
|
|
12
|
+
if (typeof IntersectionObserver == "undefined") {
|
|
13
|
+
l(!0);
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
const o = new IntersectionObserver((R) => {
|
|
17
|
+
R.some((h) => h.isIntersecting) && (l(!0), o.disconnect());
|
|
18
|
+
});
|
|
19
|
+
return o.observe(s), () => o.disconnect();
|
|
20
|
+
}, [e, i]);
|
|
21
|
+
const r = y || !c, I = (s) => {
|
|
22
|
+
v(!0), n == null || n(s);
|
|
23
|
+
};
|
|
24
|
+
return /* @__PURE__ */ z(
|
|
25
|
+
"span",
|
|
26
|
+
{
|
|
27
|
+
className: N("smwb-lazy-image", g, { "smwb-lazy-image--empty": r }),
|
|
28
|
+
style: m != null ? { aspectRatio: String(m) } : void 0,
|
|
29
|
+
children: [
|
|
30
|
+
r && a ? /* @__PURE__ */ u("span", { className: "smwb-lazy-image__fallback", children: a }) : null,
|
|
31
|
+
r ? null : /* @__PURE__ */ u(
|
|
32
|
+
"img",
|
|
33
|
+
{
|
|
34
|
+
...b,
|
|
35
|
+
ref: w,
|
|
36
|
+
className: "smwb-lazy-image__img",
|
|
37
|
+
src: i ? c : void 0,
|
|
38
|
+
alt: t != null ? t : "",
|
|
39
|
+
loading: e ? "lazy" : void 0,
|
|
40
|
+
decoding: "async",
|
|
41
|
+
onError: I
|
|
42
|
+
}
|
|
43
|
+
)
|
|
44
|
+
]
|
|
45
|
+
}
|
|
46
|
+
);
|
|
47
|
+
});
|
|
48
|
+
export {
|
|
49
|
+
A as LazyImage,
|
|
50
|
+
A as default
|
|
51
|
+
};
|
|
52
|
+
//# sourceMappingURL=lazyImage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lazyImage.js","sources":["../../../../src/components/dataDisplay/lazyImage/lazyImage.tsx"],"sourcesContent":["import React, { forwardRef, useEffect, useRef, useState } from \"react\";\nimport cn from \"clsx\";\nimport { useForkRef } from \"../../../hooks/useForkRef\";\n\nexport interface LazyImageProps extends Omit<React.ImgHTMLAttributes<HTMLImageElement>, \"onError\"> {\n /** Image URL. When absent (or after a load error) the `fallback` is shown. */\n src?: string | undefined;\n alt?: string | undefined;\n /** Rendered in place of the image when it is missing or fails to load. */\n fallback?: React.ReactNode;\n /** Defer loading until the image scrolls into view (IntersectionObserver). Default true. */\n lazy?: boolean;\n /** CSS `aspect-ratio` for the wrapper (e.g. `1`, `\"4 / 3\"`) to reserve space before load. */\n aspectRatio?: string | number;\n /** Fires on a load error (after the fallback is swapped in). */\n onError?: (event: React.SyntheticEvent<HTMLImageElement>) => void;\n}\n\n/**\n * An `<img>` with a built-in `onError` fallback and optional in-viewport lazy\n * loading — the `<img decoding=async onError=…>` + fallback dance hand-rolled in\n * every gallery, in one primitive. SSR-safe: renders the image markup on the\n * server; the IntersectionObserver only runs in an effect on the client.\n */\nexport const LazyImage = forwardRef<HTMLImageElement, LazyImageProps>(function LazyImage(\n { src, alt, fallback, lazy = true, aspectRatio, className, onError, ...rest },\n ref\n) {\n const [failed, setFailed] = useState(false);\n const [visible, setVisible] = useState(!lazy);\n const imgRef = useRef<HTMLImageElement | null>(null);\n const setRefs = useForkRef(ref, imgRef);\n\n useEffect(() => {\n if (!lazy || visible) return;\n const el = imgRef.current;\n if (!el) return;\n if (typeof IntersectionObserver === \"undefined\") {\n setVisible(true);\n return;\n }\n const io = new IntersectionObserver((entries) => {\n if (entries.some((entry) => entry.isIntersecting)) {\n setVisible(true);\n io.disconnect();\n }\n });\n io.observe(el);\n return () => io.disconnect();\n }, [lazy, visible]);\n\n const showFallback = failed || !src;\n const handleError = (event: React.SyntheticEvent<HTMLImageElement>): void => {\n setFailed(true);\n onError?.(event);\n };\n\n return (\n <span\n className={cn(\"smwb-lazy-image\", className, { \"smwb-lazy-image--empty\": showFallback })}\n style={aspectRatio != null ? { aspectRatio: String(aspectRatio) } : undefined}\n >\n {showFallback && fallback ? <span className=\"smwb-lazy-image__fallback\">{fallback}</span> : null}\n {!showFallback ? (\n <img\n {...rest}\n ref={setRefs}\n className=\"smwb-lazy-image__img\"\n src={visible ? src : undefined}\n alt={alt ?? \"\"}\n loading={lazy ? \"lazy\" : undefined}\n decoding=\"async\"\n onError={handleError}\n />\n ) : null}\n </span>\n );\n});\n\nexport default LazyImage;\n"],"names":["LazyImage","forwardRef","src","alt","fallback","lazy","aspectRatio","className","onError","rest","ref","failed","setFailed","useState","visible","setVisible","imgRef","useRef","setRefs","useForkRef","useEffect","el","io","entries","entry","showFallback","handleError","event","jsxs","cn","jsx"],"mappings":";;;;;AAyBO,MAAMA,IAAYC,EAA6C,SACpE,EAAE,KAAAC,GAAK,KAAAC,GAAK,UAAAC,GAAU,MAAAC,IAAO,IAAM,aAAAC,GAAa,WAAAC,GAAW,SAAAC,GAAS,GAAGC,EAAA,GACvEC,GACA;AACA,QAAM,CAACC,GAAQC,CAAS,IAAIC,EAAS,EAAK,GACpC,CAACC,GAASC,CAAU,IAAIF,EAAS,CAACR,CAAI,GACtCW,IAASC,EAAgC,IAAI,GAC7CC,IAAUC,EAAWT,GAAKM,CAAM;AAEtC,EAAAI,EAAU,MAAM;AACd,QAAI,CAACf,KAAQS,EAAS;AACtB,UAAMO,IAAKL,EAAO;AAClB,QAAI,CAACK,EAAI;AACT,QAAI,OAAO,wBAAyB,aAAa;AAC/C,MAAAN,EAAW,EAAI;AACf;AAAA,IACF;AACA,UAAMO,IAAK,IAAI,qBAAqB,CAACC,MAAY;AAC/C,MAAIA,EAAQ,KAAK,CAACC,MAAUA,EAAM,cAAc,MAC9CT,EAAW,EAAI,GACfO,EAAG,WAAA;AAAA,IAEP,CAAC;AACD,WAAAA,EAAG,QAAQD,CAAE,GACN,MAAMC,EAAG,WAAA;AAAA,EAClB,GAAG,CAACjB,GAAMS,CAAO,CAAC;AAElB,QAAMW,IAAed,KAAU,CAACT,GAC1BwB,IAAc,CAACC,MAAwD;AAC3E,IAAAf,EAAU,EAAI,GACdJ,KAAA,QAAAA,EAAUmB;AAAA,EACZ;AAEA,SACE,gBAAAC;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAWC,EAAG,mBAAmBtB,GAAW,EAAE,0BAA0BkB,GAAc;AAAA,MACtF,OAAOnB,KAAe,OAAO,EAAE,aAAa,OAAOA,CAAW,MAAM;AAAA,MAEnE,UAAA;AAAA,QAAAmB,KAAgBrB,IAAW,gBAAA0B,EAAC,QAAA,EAAK,WAAU,6BAA6B,aAAS,IAAU;AAAA,QAC1FL,IAWE,OAVF,gBAAAK;AAAA,UAAC;AAAA,UAAA;AAAA,YACE,GAAGrB;AAAA,YACJ,KAAKS;AAAA,YACL,WAAU;AAAA,YACV,KAAKJ,IAAUZ,IAAM;AAAA,YACrB,KAAKC,KAAA,OAAAA,IAAO;AAAA,YACZ,SAASE,IAAO,SAAS;AAAA,YACzB,UAAS;AAAA,YACT,SAASqB;AAAA,UAAA;AAAA,QAAA;AAAA,MAET;AAAA,IAAA;AAAA,EAAA;AAGV,CAAC;"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
export interface ThumbCardProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "onSelect"> {
|
|
3
|
+
/** Thumbnail URL; falls back to `fallback` when missing / failed. */
|
|
4
|
+
src?: string;
|
|
5
|
+
caption?: React.ReactNode;
|
|
6
|
+
selected?: boolean;
|
|
7
|
+
/** Makes the card a selectable button (keyboard + `aria-pressed`). */
|
|
8
|
+
onSelect?: () => void;
|
|
9
|
+
/** Shown in place of the image when `src` is missing / fails. */
|
|
10
|
+
fallback?: React.ReactNode;
|
|
11
|
+
/** A larger preview shown in a floating popup after a hover delay. */
|
|
12
|
+
hoverPreview?: React.ReactNode | string;
|
|
13
|
+
/** Top-left overlay slot (e.g. a favourite star). */
|
|
14
|
+
topStart?: React.ReactNode;
|
|
15
|
+
/** Top-right overlay slot (e.g. a kebab menu). */
|
|
16
|
+
topEnd?: React.ReactNode;
|
|
17
|
+
lazy?: boolean;
|
|
18
|
+
disabled?: boolean;
|
|
19
|
+
/** Delay (ms) before the hover preview appears. Default 350. */
|
|
20
|
+
hoverDelay?: number;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* A selectable gallery card: image with an `onError` fallback + optional lazy
|
|
24
|
+
* load, keyboard/`aria-pressed` selection, corner action slots, and a delayed
|
|
25
|
+
* floating hover-preview. The generic gallery-card behaviour every app rebuilds
|
|
26
|
+
* on top of the primitives. SSR-safe — the hover preview is client-only.
|
|
27
|
+
*/
|
|
28
|
+
export declare const ThumbCard: React.ForwardRefExoticComponent<ThumbCardProps & React.RefAttributes<HTMLDivElement>>;
|
|
29
|
+
export default ThumbCard;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { jsxs as p, jsx as s } from "react/jsx-runtime";
|
|
2
|
+
import '../../../assets/styles/less/components/thumbCard/thumbCard.entry.css';/* empty css */
|
|
3
|
+
import { forwardRef as L, useRef as _, useState as j, useEffect as D } from "react";
|
|
4
|
+
import { createPortal as I } from "react-dom";
|
|
5
|
+
import M from "clsx";
|
|
6
|
+
import { useForkRef as z } from "../../../hooks/useForkRef.js";
|
|
7
|
+
import { LazyImage as B } from "../lazyImage/lazyImage.js";
|
|
8
|
+
const Q = L(function({
|
|
9
|
+
src: w,
|
|
10
|
+
caption: c,
|
|
11
|
+
selected: i,
|
|
12
|
+
onSelect: r,
|
|
13
|
+
fallback: v,
|
|
14
|
+
hoverPreview: a,
|
|
15
|
+
topStart: d,
|
|
16
|
+
topEnd: l,
|
|
17
|
+
lazy: y = !0,
|
|
18
|
+
disabled: n,
|
|
19
|
+
hoverDelay: g = 350,
|
|
20
|
+
className: N,
|
|
21
|
+
...R
|
|
22
|
+
}, x) {
|
|
23
|
+
const f = _(null), T = z(x, f), [u, b] = j(null), o = _(null), e = () => {
|
|
24
|
+
o.current && (clearTimeout(o.current), o.current = null);
|
|
25
|
+
}, k = () => {
|
|
26
|
+
a == null || n || (e(), o.current = setTimeout(() => {
|
|
27
|
+
var h;
|
|
28
|
+
const t = (h = f.current) == null ? void 0 : h.getBoundingClientRect();
|
|
29
|
+
t && b({ top: t.top, left: t.right + 8 });
|
|
30
|
+
}, g));
|
|
31
|
+
}, C = () => {
|
|
32
|
+
e(), b(null);
|
|
33
|
+
};
|
|
34
|
+
D(() => e, []);
|
|
35
|
+
const m = !!r && !n, E = (t) => {
|
|
36
|
+
m && (t.key === "Enter" || t.key === " ") && (t.preventDefault(), r == null || r());
|
|
37
|
+
};
|
|
38
|
+
return /* @__PURE__ */ p(
|
|
39
|
+
"div",
|
|
40
|
+
{
|
|
41
|
+
...R,
|
|
42
|
+
ref: T,
|
|
43
|
+
className: M("smwb-thumb-card", N, {
|
|
44
|
+
"smwb-thumb-card--selected": i,
|
|
45
|
+
"smwb-thumb-card--disabled": n,
|
|
46
|
+
"smwb-thumb-card--interactive": m
|
|
47
|
+
}),
|
|
48
|
+
role: m ? "button" : void 0,
|
|
49
|
+
tabIndex: m ? 0 : void 0,
|
|
50
|
+
"aria-pressed": r ? i != null ? i : !1 : void 0,
|
|
51
|
+
"aria-disabled": n || void 0,
|
|
52
|
+
onClick: m ? () => r == null ? void 0 : r() : void 0,
|
|
53
|
+
onKeyDown: E,
|
|
54
|
+
onMouseEnter: k,
|
|
55
|
+
onMouseLeave: C,
|
|
56
|
+
children: [
|
|
57
|
+
/* @__PURE__ */ p("div", { className: "smwb-thumb-card__media", children: [
|
|
58
|
+
/* @__PURE__ */ s(B, { src: w, lazy: y, fallback: v }),
|
|
59
|
+
d ? /* @__PURE__ */ s("div", { className: "smwb-thumb-card__slot smwb-thumb-card__slot--start", children: d }) : null,
|
|
60
|
+
l ? /* @__PURE__ */ s("div", { className: "smwb-thumb-card__slot smwb-thumb-card__slot--end", children: l }) : null
|
|
61
|
+
] }),
|
|
62
|
+
c ? /* @__PURE__ */ s("div", { className: "smwb-thumb-card__caption", children: c }) : null,
|
|
63
|
+
u && typeof document != "undefined" ? I(
|
|
64
|
+
/* @__PURE__ */ s(
|
|
65
|
+
"div",
|
|
66
|
+
{
|
|
67
|
+
className: "smwb-thumb-card__preview",
|
|
68
|
+
style: { position: "fixed", top: u.top, left: u.left },
|
|
69
|
+
children: typeof a == "string" ? /* @__PURE__ */ s("img", { src: a, alt: "" }) : a
|
|
70
|
+
}
|
|
71
|
+
),
|
|
72
|
+
document.body
|
|
73
|
+
) : null
|
|
74
|
+
]
|
|
75
|
+
}
|
|
76
|
+
);
|
|
77
|
+
});
|
|
78
|
+
export {
|
|
79
|
+
Q as ThumbCard,
|
|
80
|
+
Q as default
|
|
81
|
+
};
|
|
82
|
+
//# sourceMappingURL=thumbCard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"thumbCard.js","sources":["../../../../src/components/dataDisplay/thumbCard/thumbCard.tsx"],"sourcesContent":["import React, { forwardRef, useEffect, useRef, useState } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport cn from \"clsx\";\nimport { LazyImage } from \"../lazyImage\";\nimport { useForkRef } from \"../../../hooks/useForkRef\";\n\nexport interface ThumbCardProps extends Omit<React.HTMLAttributes<HTMLDivElement>, \"onSelect\"> {\n /** Thumbnail URL; falls back to `fallback` when missing / failed. */\n src?: string;\n caption?: React.ReactNode;\n selected?: boolean;\n /** Makes the card a selectable button (keyboard + `aria-pressed`). */\n onSelect?: () => void;\n /** Shown in place of the image when `src` is missing / fails. */\n fallback?: React.ReactNode;\n /** A larger preview shown in a floating popup after a hover delay. */\n hoverPreview?: React.ReactNode | string;\n /** Top-left overlay slot (e.g. a favourite star). */\n topStart?: React.ReactNode;\n /** Top-right overlay slot (e.g. a kebab menu). */\n topEnd?: React.ReactNode;\n lazy?: boolean;\n disabled?: boolean;\n /** Delay (ms) before the hover preview appears. Default 350. */\n hoverDelay?: number;\n}\n\n/**\n * A selectable gallery card: image with an `onError` fallback + optional lazy\n * load, keyboard/`aria-pressed` selection, corner action slots, and a delayed\n * floating hover-preview. The generic gallery-card behaviour every app rebuilds\n * on top of the primitives. SSR-safe — the hover preview is client-only.\n */\nexport const ThumbCard = forwardRef<HTMLDivElement, ThumbCardProps>(function ThumbCard(\n {\n src,\n caption,\n selected,\n onSelect,\n fallback,\n hoverPreview,\n topStart,\n topEnd,\n lazy = true,\n disabled,\n hoverDelay = 350,\n className,\n ...rest\n },\n ref\n) {\n const cardRef = useRef<HTMLDivElement | null>(null);\n const setRefs = useForkRef(ref, cardRef);\n const [preview, setPreview] = useState<{ top: number; left: number } | null>(null);\n const timer = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const clearTimer = (): void => {\n if (timer.current) {\n clearTimeout(timer.current);\n timer.current = null;\n }\n };\n const onEnter = (): void => {\n if (hoverPreview == null || disabled) return;\n clearTimer();\n timer.current = setTimeout(() => {\n const rect = cardRef.current?.getBoundingClientRect();\n if (rect) setPreview({ top: rect.top, left: rect.right + 8 });\n }, hoverDelay);\n };\n const onLeave = (): void => {\n clearTimer();\n setPreview(null);\n };\n useEffect(() => clearTimer, []);\n\n const interactive = !!onSelect && !disabled;\n const onKeyDown = (event: React.KeyboardEvent<HTMLDivElement>): void => {\n if (interactive && (event.key === \"Enter\" || event.key === \" \")) {\n event.preventDefault();\n onSelect?.();\n }\n };\n\n return (\n <div\n {...rest}\n ref={setRefs}\n className={cn(\"smwb-thumb-card\", className, {\n \"smwb-thumb-card--selected\": selected,\n \"smwb-thumb-card--disabled\": disabled,\n \"smwb-thumb-card--interactive\": interactive,\n })}\n role={interactive ? \"button\" : undefined}\n tabIndex={interactive ? 0 : undefined}\n aria-pressed={onSelect ? (selected ?? false) : undefined}\n aria-disabled={disabled || undefined}\n onClick={interactive ? () => onSelect?.() : undefined}\n onKeyDown={onKeyDown}\n onMouseEnter={onEnter}\n onMouseLeave={onLeave}\n >\n <div className=\"smwb-thumb-card__media\">\n <LazyImage src={src} lazy={lazy} fallback={fallback} />\n {topStart ? <div className=\"smwb-thumb-card__slot smwb-thumb-card__slot--start\">{topStart}</div> : null}\n {topEnd ? <div className=\"smwb-thumb-card__slot smwb-thumb-card__slot--end\">{topEnd}</div> : null}\n </div>\n {caption ? <div className=\"smwb-thumb-card__caption\">{caption}</div> : null}\n {preview && typeof document !== \"undefined\"\n ? createPortal(\n <div\n className=\"smwb-thumb-card__preview\"\n style={{ position: \"fixed\", top: preview.top, left: preview.left }}\n >\n {typeof hoverPreview === \"string\" ? <img src={hoverPreview} alt=\"\" /> : hoverPreview}\n </div>,\n document.body\n )\n : null}\n </div>\n );\n});\n\nexport default ThumbCard;\n"],"names":["ThumbCard","forwardRef","src","caption","selected","onSelect","fallback","hoverPreview","topStart","topEnd","lazy","disabled","hoverDelay","className","rest","ref","cardRef","useRef","setRefs","useForkRef","preview","setPreview","useState","timer","clearTimer","onEnter","rect","_a","onLeave","useEffect","interactive","onKeyDown","event","jsxs","cn","jsx","LazyImage","createPortal"],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
export interface SaveAssetDialogProps {
|
|
3
|
+
open: boolean;
|
|
4
|
+
title?: string;
|
|
5
|
+
/** Label for the name field. Omit `onNameChange` AND `name` to hide the field. */
|
|
6
|
+
nameLabel?: string;
|
|
7
|
+
name?: string;
|
|
8
|
+
onNameChange?: (name: string) => void;
|
|
9
|
+
/** Preview image URL (e.g. a freshly captured thumbnail). */
|
|
10
|
+
previewSrc?: string;
|
|
11
|
+
/** Shows a Capture button when provided. */
|
|
12
|
+
onCapture?: () => void;
|
|
13
|
+
captureLabel?: string;
|
|
14
|
+
/** Disables the actions + name field while a save/capture is in flight. */
|
|
15
|
+
busy?: boolean;
|
|
16
|
+
confirmLabel?: string;
|
|
17
|
+
cancelLabel?: string;
|
|
18
|
+
onConfirm: () => void;
|
|
19
|
+
onClose: () => void;
|
|
20
|
+
/** Extra content between the name field/preview and the actions. */
|
|
21
|
+
children?: React.ReactNode;
|
|
22
|
+
className?: string;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* A "name it / preview a thumbnail / confirm-cancel" dialog on `Modal` — the
|
|
26
|
+
* save/capture flow apps hand-build for every asset. Pairs with srv-solid's
|
|
27
|
+
* asset store: `onConfirm` uploads the captured `previewSrc`.
|
|
28
|
+
*/
|
|
29
|
+
export declare function SaveAssetDialog({ open, title, nameLabel, name, onNameChange, previewSrc, onCapture, captureLabel, busy, confirmLabel, cancelLabel, onConfirm, onClose, children, className, }: SaveAssetDialogProps): React.ReactElement;
|
|
30
|
+
export default SaveAssetDialog;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { jsxs as u, jsx as i } from "react/jsx-runtime";
|
|
2
|
+
import '../../../assets/styles/less/components/saveAssetDialog/saveAssetDialog.entry.css';/* empty css */
|
|
3
|
+
import T from "clsx";
|
|
4
|
+
import { Modal as l } from "../modal/modal.js";
|
|
5
|
+
import { TextField as c } from "../../inputs/textField/textField.js";
|
|
6
|
+
import { Button as w } from "../../inputs/button/button.js";
|
|
7
|
+
function H({
|
|
8
|
+
open: k,
|
|
9
|
+
title: o,
|
|
10
|
+
nameLabel: t,
|
|
11
|
+
name: d,
|
|
12
|
+
onNameChange: s,
|
|
13
|
+
previewSrc: _,
|
|
14
|
+
onCapture: f,
|
|
15
|
+
captureLabel: v,
|
|
16
|
+
busy: r,
|
|
17
|
+
confirmLabel: x,
|
|
18
|
+
cancelLabel: p,
|
|
19
|
+
onConfirm: F,
|
|
20
|
+
onClose: h,
|
|
21
|
+
children: j,
|
|
22
|
+
className: m
|
|
23
|
+
}) {
|
|
24
|
+
const z = s !== void 0 || d !== void 0;
|
|
25
|
+
return /* @__PURE__ */ u(l, { open: k, onClose: h, size: "small", children: [
|
|
26
|
+
/* @__PURE__ */ i(l.Header, { children: o != null ? o : "Save" }),
|
|
27
|
+
/* @__PURE__ */ i(l.Content, { children: /* @__PURE__ */ u("div", { className: T("smwb-save-asset-dialog__body", m), children: [
|
|
28
|
+
z ? /* @__PURE__ */ i(
|
|
29
|
+
c,
|
|
30
|
+
{
|
|
31
|
+
label: t != null ? t : "Name",
|
|
32
|
+
value: d != null ? d : "",
|
|
33
|
+
disabled: !!r,
|
|
34
|
+
onChange: (S) => s == null ? void 0 : s(S.currentTarget.value)
|
|
35
|
+
}
|
|
36
|
+
) : null,
|
|
37
|
+
_ ? /* @__PURE__ */ i("div", { className: "smwb-save-asset-dialog__preview", children: /* @__PURE__ */ i("img", { src: _, alt: "" }) }) : null,
|
|
38
|
+
f ? /* @__PURE__ */ i(
|
|
39
|
+
w,
|
|
40
|
+
{
|
|
41
|
+
variant: "outlined",
|
|
42
|
+
size: "small",
|
|
43
|
+
disabled: !!r,
|
|
44
|
+
onClick: () => f(),
|
|
45
|
+
label: v != null ? v : "Capture preview"
|
|
46
|
+
}
|
|
47
|
+
) : null,
|
|
48
|
+
j
|
|
49
|
+
] }) }),
|
|
50
|
+
/* @__PURE__ */ u(l.Footer, { children: [
|
|
51
|
+
/* @__PURE__ */ i(w, { variant: "text", disabled: !!r, onClick: () => h(), label: p != null ? p : "Cancel" }),
|
|
52
|
+
/* @__PURE__ */ i(w, { variant: "contained", disabled: !!r, onClick: () => F(), label: x != null ? x : "Save" })
|
|
53
|
+
] })
|
|
54
|
+
] });
|
|
55
|
+
}
|
|
56
|
+
export {
|
|
57
|
+
H as SaveAssetDialog,
|
|
58
|
+
H as default
|
|
59
|
+
};
|
|
60
|
+
//# sourceMappingURL=saveAssetDialog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"saveAssetDialog.js","sources":["../../../../src/components/feedBack/saveAssetDialog/saveAssetDialog.tsx"],"sourcesContent":["import React from \"react\";\nimport cn from \"clsx\";\nimport { Modal } from \"../modal\";\nimport { Button } from \"../../inputs/button\";\nimport { TextField } from \"../../inputs/textField\";\n\nexport interface SaveAssetDialogProps {\n open: boolean;\n title?: string;\n /** Label for the name field. Omit `onNameChange` AND `name` to hide the field. */\n nameLabel?: string;\n name?: string;\n onNameChange?: (name: string) => void;\n /** Preview image URL (e.g. a freshly captured thumbnail). */\n previewSrc?: string;\n /** Shows a Capture button when provided. */\n onCapture?: () => void;\n captureLabel?: string;\n /** Disables the actions + name field while a save/capture is in flight. */\n busy?: boolean;\n confirmLabel?: string;\n cancelLabel?: string;\n onConfirm: () => void;\n onClose: () => void;\n /** Extra content between the name field/preview and the actions. */\n children?: React.ReactNode;\n className?: string;\n}\n\n/**\n * A \"name it / preview a thumbnail / confirm-cancel\" dialog on `Modal` — the\n * save/capture flow apps hand-build for every asset. Pairs with srv-solid's\n * asset store: `onConfirm` uploads the captured `previewSrc`.\n */\nexport function SaveAssetDialog({\n open,\n title,\n nameLabel,\n name,\n onNameChange,\n previewSrc,\n onCapture,\n captureLabel,\n busy,\n confirmLabel,\n cancelLabel,\n onConfirm,\n onClose,\n children,\n className,\n}: SaveAssetDialogProps): React.ReactElement {\n const showNameField = onNameChange !== undefined || name !== undefined;\n\n return (\n <Modal open={open} onClose={onClose} size=\"small\">\n <Modal.Header>{title ?? \"Save\"}</Modal.Header>\n <Modal.Content>\n <div className={cn(\"smwb-save-asset-dialog__body\", className)}>\n {showNameField ? (\n <TextField\n label={nameLabel ?? \"Name\"}\n value={name ?? \"\"}\n disabled={!!busy}\n onChange={(event) => onNameChange?.(event.currentTarget.value)}\n />\n ) : null}\n {previewSrc ? (\n <div className=\"smwb-save-asset-dialog__preview\">\n <img src={previewSrc} alt=\"\" />\n </div>\n ) : null}\n {onCapture ? (\n <Button\n variant=\"outlined\"\n size=\"small\"\n disabled={!!busy}\n onClick={() => onCapture()}\n label={captureLabel ?? \"Capture preview\"}\n />\n ) : null}\n {children}\n </div>\n </Modal.Content>\n <Modal.Footer>\n <Button variant=\"text\" disabled={!!busy} onClick={() => onClose()} label={cancelLabel ?? \"Cancel\"} />\n <Button variant=\"contained\" disabled={!!busy} onClick={() => onConfirm()} label={confirmLabel ?? \"Save\"} />\n </Modal.Footer>\n </Modal>\n );\n}\n\nexport default SaveAssetDialog;\n"],"names":["SaveAssetDialog","open","title","nameLabel","name","onNameChange","previewSrc","onCapture","captureLabel","busy","confirmLabel","cancelLabel","onConfirm","onClose","children","className","showNameField","jsxs","Modal","jsx","cn","TextField","event","Button"],"mappings":";;;;;;AAmCO,SAASA,EAAgB;AAAA,EAC9B,MAAAC;AAAA,EACA,OAAAC;AAAA,EACA,WAAAC;AAAA,EACA,MAAAC;AAAA,EACA,cAAAC;AAAA,EACA,YAAAC;AAAA,EACA,WAAAC;AAAA,EACA,cAAAC;AAAA,EACA,MAAAC;AAAA,EACA,cAAAC;AAAA,EACA,aAAAC;AAAA,EACA,WAAAC;AAAA,EACA,SAAAC;AAAA,EACA,UAAAC;AAAA,EACA,WAAAC;AACF,GAA6C;AAC3C,QAAMC,IAAgBX,MAAiB,UAAaD,MAAS;AAE7D,SACE,gBAAAa,EAACC,GAAA,EAAM,MAAAjB,GAAY,SAAAY,GAAkB,MAAK,SACxC,UAAA;AAAA,IAAA,gBAAAM,EAACD,EAAM,QAAN,EAAc,UAAAhB,KAAA,OAAAA,IAAS,QAAO;AAAA,IAC/B,gBAAAiB,EAACD,EAAM,SAAN,EACC,UAAA,gBAAAD,EAAC,SAAI,WAAWG,EAAG,gCAAgCL,CAAS,GACzD,UAAA;AAAA,MAAAC,IACC,gBAAAG;AAAA,QAACE;AAAA,QAAA;AAAA,UACC,OAAOlB,KAAA,OAAAA,IAAa;AAAA,UACpB,OAAOC,KAAA,OAAAA,IAAQ;AAAA,UACf,UAAU,CAAC,CAACK;AAAA,UACZ,UAAU,CAACa,MAAUjB,KAAA,gBAAAA,EAAeiB,EAAM,cAAc;AAAA,QAAK;AAAA,MAAA,IAE7D;AAAA,MACHhB,IACC,gBAAAa,EAAC,OAAA,EAAI,WAAU,mCACb,UAAA,gBAAAA,EAAC,OAAA,EAAI,KAAKb,GAAY,KAAI,GAAA,CAAG,EAAA,CAC/B,IACE;AAAA,MACHC,IACC,gBAAAY;AAAA,QAACI;AAAA,QAAA;AAAA,UACC,SAAQ;AAAA,UACR,MAAK;AAAA,UACL,UAAU,CAAC,CAACd;AAAA,UACZ,SAAS,MAAMF,EAAA;AAAA,UACf,OAAOC,KAAA,OAAAA,IAAgB;AAAA,QAAA;AAAA,MAAA,IAEvB;AAAA,MACHM;AAAA,IAAA,EAAA,CACH,EAAA,CACF;AAAA,IACA,gBAAAG,EAACC,EAAM,QAAN,EACC,UAAA;AAAA,MAAA,gBAAAC,EAACI,GAAA,EAAO,SAAQ,QAAO,UAAU,CAAC,CAACd,GAAM,SAAS,MAAMI,EAAA,GAAW,OAAOF,KAAA,OAAAA,IAAe,SAAA,CAAU;AAAA,MACnG,gBAAAQ,EAACI,GAAA,EAAO,SAAQ,aAAY,UAAU,CAAC,CAACd,GAAM,SAAS,MAAMG,EAAA,GAAa,OAAOF,KAAA,OAAAA,IAAgB,OAAA,CAAQ;AAAA,IAAA,EAAA,CAC3G;AAAA,EAAA,GACF;AAEJ;"}
|