@0001-labs/design-system-1 0.3.0-alpha.13 → 0.3.0-alpha.14
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/DS1/0-face/calendar.ts +194 -0
- package/DS1/0-face/carousel.ts +623 -0
- package/DS1/0-face/component-visibility.ts +13 -0
- package/DS1/0-face/copy-text.ts +96 -0
- package/DS1/0-face/device.ts +8 -58
- package/DS1/0-face/dialog-swipe.ts +249 -0
- package/DS1/0-face/dialogs.ts +208 -0
- package/DS1/0-face/drawer.ts +258 -0
- package/DS1/0-face/feedback-words.ts +36 -0
- package/DS1/0-face/feedback.ts +40 -0
- package/DS1/0-face/format.ts +700 -0
- package/DS1/0-face/generated/toast-assets.ts +18 -0
- package/DS1/0-face/grid-fit.ts +1 -1
- package/DS1/0-face/grid.ts +3 -2
- package/DS1/0-face/header.ts +78 -0
- package/DS1/0-face/i18n.ts +93 -18
- package/DS1/0-face/keys.ts +276 -0
- package/DS1/0-face/languages.ts +4 -4
- package/DS1/0-face/layout-inspector.ts +6 -6
- package/DS1/0-face/library-styles.ts +33 -0
- package/DS1/0-face/load-toaster.ts +7 -0
- package/DS1/0-face/preference-options.ts +29 -0
- package/DS1/0-face/preferences.ts +3 -11
- package/DS1/0-face/pricing.ts +98 -43
- package/DS1/0-face/scaling.ts +160 -4
- package/DS1/0-face/shared-words.ts +9 -4
- package/DS1/0-face/sidebar.ts +201 -0
- package/DS1/0-face/theme-bootstrap.js +184 -0
- package/DS1/0-face/theme.ts +89 -47
- package/DS1/0-face/toast-queue.ts +157 -0
- package/DS1/0-face/toaster.ts +384 -0
- package/DS1/0-face/tooltips.ts +157 -15
- package/DS1/0-face/translations/da.json +60 -1
- package/DS1/0-face/translations/de.json +60 -1
- package/DS1/0-face/translations/en.json +60 -1
- package/DS1/0-face/translations/es.json +60 -1
- package/DS1/0-face/translations/fi.json +60 -1
- package/DS1/0-face/translations/fr.json +60 -1
- package/DS1/0-face/translations/is.json +60 -1
- package/DS1/0-face/translations/it.json +60 -1
- package/DS1/0-face/translations/ja.json +60 -1
- package/DS1/0-face/translations/ko.json +60 -1
- package/DS1/0-face/translations/nb.json +60 -1
- package/DS1/0-face/translations/pt-BR.json +60 -1
- package/DS1/0-face/translations/pt.json +60 -1
- package/DS1/0-face/translations/sv.json +60 -1
- package/DS1/0-face/translations/zh.json +60 -1
- package/DS1/0-face/translations-format.ts +3 -4
- package/DS1/1-root/card.css +192 -0
- package/DS1/1-root/carousel.css +136 -0
- package/DS1/1-root/cjk.css +23 -0
- package/DS1/1-root/component-metrics.css +1 -0
- package/DS1/1-root/component-tokens.css +51 -8
- package/DS1/1-root/controls.css +887 -14
- package/DS1/1-root/dialog-placement.css +191 -0
- package/DS1/1-root/document.css +183 -0
- package/DS1/1-root/drawer.css +83 -0
- package/DS1/1-root/empty.css +83 -0
- package/DS1/1-root/figures.css +141 -0
- package/DS1/1-root/fonts/Iosevka-LICENSE.md +3 -1
- package/DS1/1-root/fonts/Iosevka-Regular.woff2 +0 -0
- package/DS1/1-root/fonts.css +69 -0
- package/DS1/1-root/footer.css +186 -0
- package/DS1/1-root/header.css +165 -0
- package/DS1/1-root/kbd.css +46 -0
- package/DS1/1-root/library-tokens.ts +91 -0
- package/DS1/1-root/measures.ts +53 -0
- package/DS1/1-root/notice.css +165 -0
- package/DS1/1-root/one.css +14 -84
- package/DS1/1-root/one.semantic.css +200 -148
- package/DS1/1-root/palette.css +58 -0
- package/DS1/1-root/palette.ts +19 -0
- package/DS1/1-root/progress.css +356 -0
- package/DS1/1-root/prose.css +202 -0
- package/DS1/1-root/row.css +297 -0
- package/DS1/1-root/table.css +111 -0
- package/DS1/1-root/text.css +70 -0
- package/DS1/2-core/button-split.ts +55 -0
- package/DS1/2-core/chart/chart.css +169 -0
- package/DS1/2-core/chart/grid-chart.ts +554 -0
- package/DS1/2-core/ds-avatar.ts +25 -6
- package/DS1/2-core/ds-badge.ts +10 -10
- package/DS1/2-core/ds-button.ts +111 -26
- package/DS1/2-core/ds-card.ts +135 -105
- package/DS1/2-core/ds-chart.ts +327 -0
- package/DS1/2-core/ds-composer.ts +8 -2
- package/DS1/2-core/ds-cycle.ts +97 -21
- package/DS1/2-core/ds-empty.ts +120 -0
- package/DS1/2-core/ds-icon.ts +11 -2
- package/DS1/2-core/ds-input.ts +165 -6
- package/DS1/2-core/ds-kbd.ts +78 -0
- package/DS1/2-core/ds-loading.ts +72 -0
- package/DS1/2-core/ds-notice.ts +180 -0
- package/DS1/2-core/ds-progress.ts +380 -0
- package/DS1/2-core/ds-spacing-handle.ts +22 -0
- package/DS1/2-core/ds-stat.ts +174 -0
- package/DS1/2-core/ds-switch.ts +1 -0
- package/DS1/2-core/ds-text.ts +15 -2
- package/DS1/2-core/ds-toast.ts +354 -0
- package/DS1/2-core/figures.ts +105 -0
- package/DS1/2-core/generated/ds-icon-map.ts +234 -128
- package/DS1/2-core/generated/icon-avatar.ts +2 -0
- package/DS1/2-core/generated/icons-extra.ts +118 -65
- package/DS1/2-core/generated/icons-immediate.ts +1 -1
- package/DS1/2-core/spacing-handle.ts +95 -0
- package/DS1/2-core/styles/ds-avatar.css +9 -8
- package/DS1/2-core/styles/ds-button-host.css +26 -3
- package/DS1/2-core/styles/ds-button-split.css +67 -0
- package/DS1/2-core/styles/ds-button.css +49 -15
- package/DS1/2-core/styles/ds-card.css +34 -0
- package/DS1/2-core/styles/ds-composer.css +13 -0
- package/DS1/2-core/styles/ds-cycle.css +69 -0
- package/DS1/2-core/styles/ds-empty.css +18 -0
- package/DS1/2-core/styles/ds-gap.css +1 -0
- package/DS1/2-core/styles/ds-icon.css +1 -0
- package/DS1/2-core/styles/ds-input.css +59 -6
- package/DS1/2-core/styles/ds-kbd.css +12 -0
- package/DS1/2-core/styles/ds-loading.css +13 -0
- package/DS1/2-core/styles/ds-notice.css +30 -0
- package/DS1/2-core/styles/ds-progress.css +25 -0
- package/DS1/2-core/styles/ds-select.css +2 -2
- package/DS1/2-core/styles/ds-spacing-handle.css +8 -0
- package/DS1/2-core/styles/ds-split.css +2 -62
- package/DS1/2-core/styles/ds-stat.css +34 -0
- package/DS1/2-core/styles/ds-switch.css +16 -1
- package/DS1/2-core/styles/ds-text.css +43 -12
- package/DS1/2-core/styles/ds-toast.css +182 -0
- package/DS1/2-core/styles/ds-tooltip.css +1 -0
- package/DS1/3-unit/calendar-base.ts +263 -0
- package/DS1/3-unit/ds-accordion.ts +9 -1
- package/DS1/3-unit/ds-avatar-group.ts +1 -0
- package/DS1/3-unit/ds-calendar-large.ts +349 -0
- package/DS1/3-unit/ds-calendar.ts +344 -0
- package/DS1/3-unit/ds-carousel.ts +368 -0
- package/DS1/3-unit/ds-date-picker.ts +540 -0
- package/DS1/3-unit/ds-form.ts +45 -37
- package/DS1/3-unit/ds-list.ts +48 -1
- package/DS1/3-unit/ds-matrix.ts +318 -0
- package/DS1/3-unit/ds-menu.ts +8 -4
- package/DS1/3-unit/ds-row.ts +84 -1
- package/DS1/3-unit/ds-sidebar.ts +280 -0
- package/DS1/3-unit/ds-table.ts +75 -34
- package/DS1/3-unit/styles/ds-accordion.css +1 -0
- package/DS1/3-unit/styles/ds-avatar-group.css +2 -4
- package/DS1/3-unit/styles/ds-calendar-large.css +165 -0
- package/DS1/3-unit/styles/ds-calendar.css +238 -0
- package/DS1/3-unit/styles/ds-carousel.css +30 -0
- package/DS1/3-unit/styles/ds-date-picker.css +124 -0
- package/DS1/3-unit/styles/ds-list.css +1 -0
- package/DS1/3-unit/styles/ds-matrix.css +203 -0
- package/DS1/3-unit/styles/ds-menu.css +31 -6
- package/DS1/3-unit/styles/ds-row.css +84 -2
- package/DS1/3-unit/styles/ds-sidebar.css +117 -0
- package/DS1/3-unit/styles/ds-table.css +3 -74
- package/DS1/4-page/ds-dialog.ts +40 -4
- package/DS1/4-page/ds-document.ts +240 -0
- package/DS1/4-page/ds-footer.ts +165 -0
- package/DS1/4-page/ds-grid.ts +39 -59
- package/DS1/4-page/ds-header.ts +171 -0
- package/DS1/4-page/ds-page.ts +184 -0
- package/DS1/4-page/email.ts +2 -3
- package/DS1/4-page/styles/ds-container.css +1 -0
- package/DS1/4-page/styles/ds-document.css +18 -0
- package/DS1/4-page/styles/ds-footer.css +29 -0
- package/DS1/4-page/styles/ds-grid.css +31 -85
- package/DS1/4-page/styles/ds-header.css +57 -0
- package/DS1/4-page/styles/ds-page.css +214 -0
- package/DS1/components.ts +7 -1
- package/DS1/index.ts +26 -6
- package/DS1/react/avatar.ts +4 -5
- package/DS1/react/button-split.ts +29 -0
- package/DS1/react/button.ts +32 -13
- package/DS1/react/carousel.ts +76 -0
- package/DS1/react/dialog.ts +36 -5
- package/DS1/react/document.ts +14 -0
- package/DS1/react/empty.ts +32 -0
- package/DS1/react/footer.ts +17 -0
- package/DS1/react/header.ts +15 -0
- package/DS1/react/input.ts +28 -17
- package/DS1/react/kbd.ts +21 -0
- package/DS1/react/loading.ts +18 -0
- package/DS1/react/notice.ts +59 -0
- package/DS1/react/page.ts +13 -0
- package/DS1/react/progress.ts +99 -0
- package/DS1/react/sidebar.ts +60 -0
- package/DS1/react/spacing-handle.ts +21 -0
- package/DS1/react/stat.ts +73 -0
- package/DS1/react/toast.ts +82 -0
- package/DS1/x-icon/Tabler-LICENSE.md +27 -0
- package/DS1/x-icon/airtable.svg +5 -0
- package/DS1/x-icon/attach.svg +3 -0
- package/DS1/x-icon/audio.svg +3 -0
- package/DS1/x-icon/bag-alt.svg +3 -0
- package/DS1/x-icon/bank.svg +3 -0
- package/DS1/x-icon/banknote.svg +3 -0
- package/DS1/x-icon/bolt.svg +3 -0
- package/DS1/x-icon/book-alt.svg +3 -0
- package/DS1/x-icon/book.svg +4 -0
- package/DS1/x-icon/box.svg +3 -0
- package/DS1/x-icon/briefcase.svg +3 -0
- package/DS1/x-icon/building.svg +4 -0
- package/DS1/x-icon/car.svg +3 -0
- package/DS1/x-icon/card.svg +3 -0
- package/DS1/x-icon/cart.svg +3 -0
- package/DS1/x-icon/{ezo-item-button-start.svg → chevron-left.svg} +1 -1
- package/DS1/x-icon/{ezo-android-screen-stats.svg → chevron-right.svg} +1 -1
- package/DS1/x-icon/cloud.svg +3 -0
- package/DS1/x-icon/coffee.svg +3 -0
- package/DS1/x-icon/coins.svg +3 -0
- package/DS1/x-icon/cursor.svg +3 -0
- package/DS1/x-icon/curve.svg +7 -0
- package/DS1/x-icon/dislike.svg +4 -0
- package/DS1/x-icon/dot-bank.svg +3 -0
- package/DS1/x-icon/dot-banknote.svg +3 -0
- package/DS1/x-icon/dot-banknotes.svg +3 -0
- package/DS1/x-icon/dot-card.svg +3 -0
- package/DS1/x-icon/dot-coin.svg +3 -0
- package/DS1/x-icon/dot-coins.svg +3 -0
- package/DS1/x-icon/dot-receipt.svg +3 -0
- package/DS1/x-icon/dot-safe.svg +3 -0
- package/DS1/x-icon/dot-transfer.svg +3 -0
- package/DS1/x-icon/dot-wallet.svg +3 -0
- package/DS1/x-icon/download.svg +4 -0
- package/DS1/x-icon/drive.svg +5 -0
- package/DS1/x-icon/drop.svg +3 -0
- package/DS1/x-icon/dropbox.svg +3 -0
- package/DS1/x-icon/dumbbell.svg +3 -0
- package/DS1/x-icon/eye-off.svg +3 -0
- package/DS1/x-icon/eye.svg +3 -0
- package/DS1/x-icon/facebook.svg +3 -0
- package/DS1/x-icon/figma.svg +5 -0
- package/DS1/x-icon/flame.svg +3 -0
- package/DS1/x-icon/flip.svg +5 -0
- package/DS1/x-icon/food.svg +3 -0
- package/DS1/x-icon/fuel.svg +3 -0
- package/DS1/x-icon/game.svg +3 -0
- package/DS1/x-icon/gift.svg +3 -0
- package/DS1/x-icon/github.svg +3 -0
- package/DS1/x-icon/heart.svg +3 -0
- package/DS1/x-icon/history.svg +3 -0
- package/DS1/x-icon/home-alt.svg +3 -0
- package/DS1/x-icon/income.svg +3 -0
- package/DS1/x-icon/info.svg +5 -0
- package/DS1/x-icon/instagram.svg +5 -0
- package/DS1/x-icon/jpbank.svg +3 -0
- package/DS1/x-icon/key.svg +4 -0
- package/DS1/x-icon/keyboard.svg +3 -0
- package/DS1/x-icon/like.svg +4 -0
- package/DS1/x-icon/linkedin.svg +7 -0
- package/DS1/x-icon/loom.svg +6 -0
- package/DS1/x-icon/map.svg +4 -0
- package/DS1/x-icon/medical.svg +3 -0
- package/DS1/x-icon/{ezo-android-screen-lists.svg → minus.svg} +1 -1
- package/DS1/x-icon/moon.svg +3 -0
- package/DS1/x-icon/move.svg +3 -0
- package/DS1/x-icon/music-alt.svg +3 -0
- package/DS1/x-icon/music.svg +5 -0
- package/DS1/x-icon/notion.svg +6 -0
- package/DS1/x-icon/offline.svg +3 -0
- package/DS1/x-icon/pause.svg +4 -0
- package/DS1/x-icon/paw.svg +3 -0
- package/DS1/x-icon/pdf.svg +3 -0
- package/DS1/x-icon/people.svg +5 -0
- package/DS1/x-icon/percent.svg +3 -0
- package/DS1/x-icon/phone.svg +3 -0
- package/DS1/x-icon/pill.svg +3 -0
- package/DS1/x-icon/plane.svg +3 -0
- package/DS1/x-icon/postal.svg +3 -0
- package/DS1/x-icon/present.svg +4 -0
- package/DS1/x-icon/reaction.svg +5 -0
- package/DS1/x-icon/receipt.svg +3 -0
- package/DS1/x-icon/refresh.svg +3 -0
- package/DS1/x-icon/refund.svg +3 -0
- package/DS1/x-icon/repeat.svg +3 -0
- package/DS1/x-icon/rotate.svg +4 -0
- package/DS1/x-icon/safe.svg +3 -0
- package/DS1/x-icon/school-alt.svg +3 -0
- package/DS1/x-icon/shield-alt.svg +3 -0
- package/DS1/x-icon/shield.svg +4 -0
- package/DS1/x-icon/shirt.svg +3 -0
- package/DS1/x-icon/shop.svg +3 -0
- package/DS1/x-icon/sign-in.svg +3 -0
- package/DS1/x-icon/sign-out.svg +3 -0
- package/DS1/x-icon/slack.svg +6 -0
- package/DS1/x-icon/sparkle.svg +3 -0
- package/DS1/x-icon/start.svg +4 -0
- package/DS1/x-icon/{ezo-item-button-reopen.svg → stop.svg} +1 -1
- package/DS1/x-icon/sun.svg +3 -0
- package/DS1/x-icon/system.svg +4 -0
- package/DS1/x-icon/tag.svg +3 -0
- package/DS1/x-icon/ticket.svg +3 -0
- package/DS1/x-icon/title-struck.svg +4 -0
- package/DS1/x-icon/train.svg +3 -0
- package/DS1/x-icon/transfer.svg +3 -0
- package/DS1/x-icon/tv.svg +3 -0
- package/DS1/x-icon/upload.svg +4 -0
- package/DS1/x-icon/video.svg +4 -0
- package/DS1/x-icon/vimeo.svg +3 -0
- package/DS1/x-icon/wallet.svg +3 -0
- package/DS1/x-icon/wifi.svg +3 -0
- package/DS1/x-icon/window.svg +4 -0
- package/DS1/x-icon/wrench.svg +3 -0
- package/DS1/x-icon/x-brand.svg +4 -0
- package/DS1/x-icon/youtube.svg +4 -0
- package/README.md +3 -3
- package/dist/0-face/calendar.d.ts +75 -0
- package/dist/0-face/calendar.d.ts.map +1 -0
- package/dist/0-face/calendar.js +149 -0
- package/dist/0-face/carousel.d.ts +174 -0
- package/dist/0-face/carousel.d.ts.map +1 -0
- package/dist/0-face/carousel.js +583 -0
- package/dist/0-face/component-visibility.d.ts +7 -0
- package/dist/0-face/component-visibility.d.ts.map +1 -0
- package/dist/0-face/component-visibility.js +10 -0
- package/dist/0-face/copy-text.d.ts +11 -0
- package/dist/0-face/copy-text.d.ts.map +1 -0
- package/dist/0-face/copy-text.js +97 -0
- package/dist/0-face/device.d.ts +3 -7
- package/dist/0-face/device.d.ts.map +1 -1
- package/dist/0-face/device.js +7 -41
- package/dist/0-face/dialog-swipe.d.ts +49 -0
- package/dist/0-face/dialog-swipe.d.ts.map +1 -0
- package/dist/0-face/dialog-swipe.js +239 -0
- package/dist/0-face/dialogs.d.ts +33 -0
- package/dist/0-face/dialogs.d.ts.map +1 -0
- package/dist/0-face/dialogs.js +173 -0
- package/dist/0-face/drawer.d.ts +64 -0
- package/dist/0-face/drawer.d.ts.map +1 -0
- package/dist/0-face/drawer.js +256 -0
- package/dist/0-face/feedback-words.d.ts +21 -0
- package/dist/0-face/feedback-words.d.ts.map +1 -0
- package/dist/0-face/feedback-words.js +30 -0
- package/dist/0-face/feedback.d.ts +41 -0
- package/dist/0-face/feedback.d.ts.map +1 -0
- package/dist/0-face/feedback.js +35 -0
- package/dist/0-face/format.d.ts +166 -0
- package/dist/0-face/format.d.ts.map +1 -0
- package/dist/0-face/format.js +445 -0
- package/dist/0-face/generated/toast-assets.d.ts +11 -0
- package/dist/0-face/generated/toast-assets.d.ts.map +1 -0
- package/dist/0-face/generated/toast-assets.js +14 -0
- package/dist/0-face/grid-fit.js +1 -1
- package/dist/0-face/grid.d.ts.map +1 -1
- package/dist/0-face/grid.js +2 -1
- package/dist/0-face/header.d.ts +38 -0
- package/dist/0-face/header.d.ts.map +1 -0
- package/dist/0-face/header.js +80 -0
- package/dist/0-face/i18n.d.ts +32 -2
- package/dist/0-face/i18n.d.ts.map +1 -1
- package/dist/0-face/i18n.js +65 -19
- package/dist/0-face/keys.d.ts +104 -0
- package/dist/0-face/keys.d.ts.map +1 -0
- package/dist/0-face/keys.js +253 -0
- package/dist/0-face/languages.d.ts +2 -2
- package/dist/0-face/languages.js +3 -3
- package/dist/0-face/layout-inspector.js +6 -6
- package/dist/0-face/library-styles.d.ts +7 -0
- package/dist/0-face/library-styles.d.ts.map +1 -0
- package/dist/0-face/library-styles.js +29 -0
- package/dist/0-face/load-toaster.d.ts +8 -0
- package/dist/0-face/load-toaster.d.ts.map +1 -0
- package/dist/0-face/load-toaster.js +7 -0
- package/dist/0-face/preference-options.d.ts +34 -0
- package/dist/0-face/preference-options.d.ts.map +1 -0
- package/dist/0-face/preference-options.js +1 -0
- package/dist/0-face/preferences.d.ts +3 -12
- package/dist/0-face/preferences.d.ts.map +1 -1
- package/dist/0-face/pricing.d.ts +19 -9
- package/dist/0-face/pricing.d.ts.map +1 -1
- package/dist/0-face/pricing.js +81 -40
- package/dist/0-face/scaling.d.ts +71 -1
- package/dist/0-face/scaling.d.ts.map +1 -1
- package/dist/0-face/scaling.js +108 -3
- package/dist/0-face/shared-words.d.ts +9 -4
- package/dist/0-face/shared-words.d.ts.map +1 -1
- package/dist/0-face/sidebar.d.ts +69 -0
- package/dist/0-face/sidebar.d.ts.map +1 -0
- package/dist/0-face/sidebar.js +191 -0
- package/dist/0-face/theme-bootstrap.d.ts +1 -0
- package/dist/0-face/theme-bootstrap.d.ts.map +1 -0
- package/dist/0-face/theme-bootstrap.js +214 -0
- package/dist/0-face/theme.d.ts +32 -0
- package/dist/0-face/theme.d.ts.map +1 -1
- package/dist/0-face/theme.js +69 -43
- package/dist/0-face/toast-queue.d.ts +110 -0
- package/dist/0-face/toast-queue.d.ts.map +1 -0
- package/dist/0-face/toast-queue.js +98 -0
- package/dist/0-face/toaster.d.ts +27 -0
- package/dist/0-face/toaster.d.ts.map +1 -0
- package/dist/0-face/toaster.js +373 -0
- package/dist/0-face/tooltips.d.ts +24 -1
- package/dist/0-face/tooltips.d.ts.map +1 -1
- package/dist/0-face/tooltips.js +155 -16
- package/dist/0-face/translations/da.json +60 -1
- package/dist/0-face/translations/de.json +60 -1
- package/dist/0-face/translations/en.json +60 -1
- package/dist/0-face/translations/es.json +60 -1
- package/dist/0-face/translations/fi.json +60 -1
- package/dist/0-face/translations/fr.json +60 -1
- package/dist/0-face/translations/is.json +60 -1
- package/dist/0-face/translations/it.json +60 -1
- package/dist/0-face/translations/ja.json +60 -1
- package/dist/0-face/translations/ko.json +60 -1
- package/dist/0-face/translations/nb.json +60 -1
- package/dist/0-face/translations/pt-BR.json +60 -1
- package/dist/0-face/translations/pt.json +60 -1
- package/dist/0-face/translations/sv.json +60 -1
- package/dist/0-face/translations/zh.json +60 -1
- package/dist/0-face/translations-format.d.ts.map +1 -1
- package/dist/0-face/translations-format.js +3 -4
- package/dist/0-face/tree.d.ts +69 -0
- package/dist/0-face/tree.d.ts.map +1 -0
- package/dist/0-face/tree.js +191 -0
- package/dist/1-root/library-tokens.d.ts +31 -0
- package/dist/1-root/library-tokens.d.ts.map +1 -0
- package/dist/1-root/library-tokens.js +84 -0
- package/dist/1-root/measures.d.ts +52 -0
- package/dist/1-root/measures.d.ts.map +1 -0
- package/dist/1-root/measures.js +49 -0
- package/dist/1-root/palette.d.ts +5 -0
- package/dist/1-root/palette.d.ts.map +1 -1
- package/dist/1-root/palette.js +18 -0
- package/dist/2-core/button-split.d.ts +21 -0
- package/dist/2-core/button-split.d.ts.map +1 -0
- package/dist/2-core/button-split.js +48 -0
- package/dist/2-core/chart/grid-chart.d.ts +113 -0
- package/dist/2-core/chart/grid-chart.d.ts.map +1 -0
- package/dist/2-core/chart/grid-chart.js +466 -0
- package/dist/2-core/ds-avatar.d.ts +20 -3
- package/dist/2-core/ds-avatar.d.ts.map +1 -1
- package/dist/2-core/ds-avatar.js +19 -5
- package/dist/2-core/ds-badge.js +10 -13
- package/dist/2-core/ds-banner.d.ts +23 -7
- package/dist/2-core/ds-banner.d.ts.map +1 -1
- package/dist/2-core/ds-banner.js +48 -12
- package/dist/2-core/ds-button.d.ts +76 -0
- package/dist/2-core/ds-button.d.ts.map +1 -1
- package/dist/2-core/ds-button.js +101 -26
- package/dist/2-core/ds-card.d.ts +76 -11
- package/dist/2-core/ds-card.d.ts.map +1 -1
- package/dist/2-core/ds-card.js +129 -105
- package/dist/2-core/ds-chart.d.ts +105 -0
- package/dist/2-core/ds-chart.d.ts.map +1 -0
- package/dist/2-core/ds-chart.js +390 -0
- package/dist/2-core/ds-composer.d.ts +7 -0
- package/dist/2-core/ds-composer.d.ts.map +1 -1
- package/dist/2-core/ds-composer.js +1 -1
- package/dist/2-core/ds-cycle.d.ts +36 -2
- package/dist/2-core/ds-cycle.d.ts.map +1 -1
- package/dist/2-core/ds-cycle.js +95 -18
- package/dist/2-core/ds-empty.d.ts +74 -0
- package/dist/2-core/ds-empty.d.ts.map +1 -0
- package/dist/2-core/ds-empty.js +96 -0
- package/dist/2-core/ds-icon.d.ts +6 -0
- package/dist/2-core/ds-icon.d.ts.map +1 -1
- package/dist/2-core/ds-icon.js +12 -2
- package/dist/2-core/ds-input.d.ts +39 -1
- package/dist/2-core/ds-input.d.ts.map +1 -1
- package/dist/2-core/ds-input.js +150 -6
- package/dist/2-core/ds-kbd.d.ts +48 -0
- package/dist/2-core/ds-kbd.d.ts.map +1 -0
- package/dist/2-core/ds-kbd.js +65 -0
- package/dist/2-core/ds-language.d.ts +8 -1
- package/dist/2-core/ds-language.d.ts.map +1 -1
- package/dist/2-core/ds-language.js +2 -2
- package/dist/2-core/ds-loading.d.ts +40 -0
- package/dist/2-core/ds-loading.d.ts.map +1 -0
- package/dist/2-core/ds-loading.js +63 -0
- package/dist/2-core/ds-meter.d.ts +103 -0
- package/dist/2-core/ds-meter.d.ts.map +1 -0
- package/dist/2-core/ds-meter.js +124 -0
- package/dist/2-core/ds-notice.d.ts +103 -0
- package/dist/2-core/ds-notice.d.ts.map +1 -0
- package/dist/2-core/ds-notice.js +152 -0
- package/dist/2-core/ds-pagedots.d.ts +64 -7
- package/dist/2-core/ds-pagedots.d.ts.map +1 -1
- package/dist/2-core/ds-pagedots.js +124 -18
- package/dist/2-core/ds-progress.d.ts +200 -0
- package/dist/2-core/ds-progress.d.ts.map +1 -0
- package/dist/2-core/ds-progress.js +319 -0
- package/dist/2-core/ds-spacing-handle.d.ts +25 -0
- package/dist/2-core/ds-spacing-handle.d.ts.map +1 -0
- package/dist/2-core/ds-spacing-handle.js +25 -0
- package/dist/2-core/ds-split.d.ts +4 -67
- package/dist/2-core/ds-split.d.ts.map +1 -1
- package/dist/2-core/ds-split.js +4 -98
- package/dist/2-core/ds-stat.d.ts +126 -0
- package/dist/2-core/ds-stat.d.ts.map +1 -0
- package/dist/2-core/ds-stat.js +137 -0
- package/dist/2-core/ds-steps.d.ts +72 -0
- package/dist/2-core/ds-steps.d.ts.map +1 -0
- package/dist/2-core/ds-steps.js +114 -0
- package/dist/2-core/ds-switch.d.ts +1 -0
- package/dist/2-core/ds-switch.d.ts.map +1 -1
- package/dist/2-core/ds-switch.js +1 -0
- package/dist/2-core/ds-text.d.ts +15 -2
- package/dist/2-core/ds-text.d.ts.map +1 -1
- package/dist/2-core/ds-text.js +13 -0
- package/dist/2-core/ds-textarea.d.ts.map +1 -1
- package/dist/2-core/ds-textarea.js +1 -0
- package/dist/2-core/ds-toast.d.ts +139 -0
- package/dist/2-core/ds-toast.d.ts.map +1 -0
- package/dist/2-core/ds-toast.js +329 -0
- package/dist/2-core/ds-toggle.d.ts +11 -0
- package/dist/2-core/ds-toggle.d.ts.map +1 -0
- package/dist/2-core/ds-toggle.js +10 -0
- package/dist/2-core/figures.d.ts +56 -0
- package/dist/2-core/figures.d.ts.map +1 -0
- package/dist/2-core/figures.js +70 -0
- package/dist/2-core/generated/ds-icon-map.d.ts +118 -65
- package/dist/2-core/generated/ds-icon-map.d.ts.map +1 -1
- package/dist/2-core/generated/ds-icon-map.js +234 -128
- package/dist/2-core/generated/icon-avatar.d.ts +2 -0
- package/dist/2-core/generated/icon-avatar.d.ts.map +1 -0
- package/dist/2-core/generated/icon-avatar.js +2 -0
- package/dist/2-core/generated/icons-extra.d.ts.map +1 -1
- package/dist/2-core/generated/icons-extra.js +118 -65
- package/dist/2-core/generated/icons-immediate.d.ts +1 -1
- package/dist/2-core/generated/icons-immediate.d.ts.map +1 -1
- package/dist/2-core/generated/icons-immediate.js +1 -1
- package/dist/2-core/spacing-handle.d.ts +28 -0
- package/dist/2-core/spacing-handle.d.ts.map +1 -0
- package/dist/2-core/spacing-handle.js +146 -0
- package/dist/3-unit/calendar-base.d.ts +149 -0
- package/dist/3-unit/calendar-base.d.ts.map +1 -0
- package/dist/3-unit/calendar-base.js +172 -0
- package/dist/3-unit/ds-accordion.d.ts +9 -0
- package/dist/3-unit/ds-accordion.d.ts.map +1 -1
- package/dist/3-unit/ds-accordion.js +7 -1
- package/dist/3-unit/ds-avatar-group.d.ts +1 -0
- package/dist/3-unit/ds-avatar-group.d.ts.map +1 -1
- package/dist/3-unit/ds-calendar-large.d.ts +138 -0
- package/dist/3-unit/ds-calendar-large.d.ts.map +1 -0
- package/dist/3-unit/ds-calendar-large.js +305 -0
- package/dist/3-unit/ds-calendar.d.ts +175 -0
- package/dist/3-unit/ds-calendar.d.ts.map +1 -0
- package/dist/3-unit/ds-calendar.js +303 -0
- package/dist/3-unit/ds-carousel.d.ts +182 -0
- package/dist/3-unit/ds-carousel.d.ts.map +1 -0
- package/dist/3-unit/ds-carousel.js +327 -0
- package/dist/3-unit/ds-date-picker.d.ts +203 -0
- package/dist/3-unit/ds-date-picker.d.ts.map +1 -0
- package/dist/3-unit/ds-date-picker.js +499 -0
- package/dist/3-unit/ds-form.d.ts.map +1 -1
- package/dist/3-unit/ds-form.js +38 -28
- package/dist/3-unit/ds-list.d.ts +12 -0
- package/dist/3-unit/ds-list.d.ts.map +1 -1
- package/dist/3-unit/ds-list.js +52 -1
- package/dist/3-unit/ds-matrix.d.ts +146 -0
- package/dist/3-unit/ds-matrix.d.ts.map +1 -0
- package/dist/3-unit/ds-matrix.js +248 -0
- package/dist/3-unit/ds-menu.d.ts +1 -1
- package/dist/3-unit/ds-menu.d.ts.map +1 -1
- package/dist/3-unit/ds-menu.js +7 -4
- package/dist/3-unit/ds-row.d.ts +66 -0
- package/dist/3-unit/ds-row.d.ts.map +1 -1
- package/dist/3-unit/ds-row.js +80 -1
- package/dist/3-unit/ds-sidebar.d.ts +108 -0
- package/dist/3-unit/ds-sidebar.d.ts.map +1 -0
- package/dist/3-unit/ds-sidebar.js +268 -0
- package/dist/3-unit/ds-table.d.ts +28 -10
- package/dist/3-unit/ds-table.d.ts.map +1 -1
- package/dist/3-unit/ds-table.js +53 -25
- package/dist/3-unit/ds-tree.d.ts +69 -0
- package/dist/3-unit/ds-tree.d.ts.map +1 -0
- package/dist/3-unit/ds-tree.js +136 -0
- package/dist/4-page/ds-dialog.d.ts +16 -1
- package/dist/4-page/ds-dialog.d.ts.map +1 -1
- package/dist/4-page/ds-dialog.js +39 -3
- package/dist/4-page/ds-document.d.ts +98 -0
- package/dist/4-page/ds-document.d.ts.map +1 -0
- package/dist/4-page/ds-document.js +213 -0
- package/dist/4-page/ds-footer.d.ts +100 -0
- package/dist/4-page/ds-footer.d.ts.map +1 -0
- package/dist/4-page/ds-footer.js +119 -0
- package/dist/4-page/ds-grid.d.ts +32 -12
- package/dist/4-page/ds-grid.d.ts.map +1 -1
- package/dist/4-page/ds-grid.js +30 -39
- package/dist/4-page/ds-header.d.ts +84 -0
- package/dist/4-page/ds-header.d.ts.map +1 -0
- package/dist/4-page/ds-header.js +143 -0
- package/dist/4-page/ds-layout.d.ts +1 -0
- package/dist/4-page/ds-layout.d.ts.map +1 -1
- package/dist/4-page/ds-layout.js +1 -1
- package/dist/4-page/ds-page.d.ts +110 -0
- package/dist/4-page/ds-page.d.ts.map +1 -0
- package/dist/4-page/ds-page.js +155 -0
- package/dist/4-page/email.d.ts +2 -3
- package/dist/4-page/email.d.ts.map +1 -1
- package/dist/4-page/email.js +2 -3
- package/dist/components.d.ts +4 -1
- package/dist/components.d.ts.map +1 -1
- package/dist/components.js +4 -1
- package/dist/design-system-1.bundle.js +11304 -4322
- package/dist/design-system-1.bundle.js.map +1 -1
- package/dist/design-system-1.bundle.min.js +8867 -4132
- package/dist/design-system-1.bundle.min.js.map +1 -1
- package/dist/design-system-1.css +1 -1
- package/dist/feedback.js +541 -0
- package/dist/feedback.js.map +1 -0
- package/dist/icons-extra-B4Iotc7s.js +298 -0
- package/dist/icons-extra-B4Iotc7s.js.map +1 -0
- package/dist/icons-extra-C4sCgoUj.js +185 -0
- package/dist/icons-extra-C4sCgoUj.js.map +1 -0
- package/dist/icons-extra-DSav6uTU.js +300 -0
- package/dist/icons-extra-DSav6uTU.js.map +1 -0
- package/dist/icons-extra-Dc_yVWIz.js +1024 -0
- package/dist/icons-extra-Dc_yVWIz.js.map +1 -0
- package/dist/icons-extra-cfzoudMf.js +1030 -0
- package/dist/icons-extra-cfzoudMf.js.map +1 -0
- package/dist/icons-extra-g_xpwZhZ.js +631 -0
- package/dist/icons-extra-g_xpwZhZ.js.map +1 -0
- package/dist/index.d.ts +23 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +23 -6
- package/dist/react/avatar.d.ts +5 -9
- package/dist/react/avatar.d.ts.map +1 -1
- package/dist/react/avatar.js +2 -2
- package/dist/react/button-split.d.ts +19 -0
- package/dist/react/button-split.d.ts.map +1 -0
- package/dist/react/button-split.js +35 -0
- package/dist/react/button.d.ts +18 -7
- package/dist/react/button.d.ts.map +1 -1
- package/dist/react/button.js +13 -4
- package/dist/react/carousel.d.ts +63 -0
- package/dist/react/carousel.d.ts.map +1 -0
- package/dist/react/carousel.js +47 -0
- package/dist/react/choice.d.ts +1 -1
- package/dist/react/context-menu.d.ts +337 -337
- package/dist/react/dialog.d.ts +684 -678
- package/dist/react/dialog.d.ts.map +1 -1
- package/dist/react/dialog.js +29 -3
- package/dist/react/document.d.ts +11 -0
- package/dist/react/document.d.ts.map +1 -0
- package/dist/react/document.js +10 -0
- package/dist/react/empty.d.ts +34 -0
- package/dist/react/empty.d.ts.map +1 -0
- package/dist/react/empty.js +8 -0
- package/dist/react/file-picker.d.ts +1 -1
- package/dist/react/footer.d.ts +13 -0
- package/dist/react/footer.d.ts.map +1 -0
- package/dist/react/footer.js +12 -0
- package/dist/react/header.d.ts +12 -0
- package/dist/react/header.d.ts.map +1 -0
- package/dist/react/header.js +11 -0
- package/dist/react/input.d.ts +31 -9
- package/dist/react/input.d.ts.map +1 -1
- package/dist/react/input.js +94 -94
- package/dist/react/kbd.d.ts +26 -0
- package/dist/react/kbd.d.ts.map +1 -0
- package/dist/react/kbd.js +8 -0
- package/dist/react/loading.d.ts +14 -0
- package/dist/react/loading.d.ts.map +1 -0
- package/dist/react/loading.js +14 -0
- package/dist/react/meter.d.ts +64 -0
- package/dist/react/meter.d.ts.map +1 -0
- package/dist/react/meter.js +15 -0
- package/dist/react/notice.d.ts +45 -0
- package/dist/react/notice.d.ts.map +1 -0
- package/dist/react/notice.js +34 -0
- package/dist/react/page.d.ts +10 -0
- package/dist/react/page.d.ts.map +1 -0
- package/dist/react/page.js +9 -0
- package/dist/react/progress.d.ts +107 -0
- package/dist/react/progress.d.ts.map +1 -0
- package/dist/react/progress.js +47 -0
- package/dist/react/sidebar.d.ts +44 -0
- package/dist/react/sidebar.d.ts.map +1 -0
- package/dist/react/sidebar.js +41 -0
- package/dist/react/spacing-handle.d.ts +13 -0
- package/dist/react/spacing-handle.d.ts.map +1 -0
- package/dist/react/spacing-handle.js +18 -0
- package/dist/react/split.d.ts +6 -14
- package/dist/react/split.d.ts.map +1 -1
- package/dist/react/split.js +5 -31
- package/dist/react/stat.d.ts +78 -0
- package/dist/react/stat.d.ts.map +1 -0
- package/dist/react/stat.js +25 -0
- package/dist/react/steps.d.ts +36 -0
- package/dist/react/steps.d.ts.map +1 -0
- package/dist/react/steps.js +10 -0
- package/dist/react/toast.d.ts +37 -0
- package/dist/react/toast.d.ts.map +1 -0
- package/dist/react/toast.js +55 -0
- package/dist/react/tree.d.ts +31 -0
- package/dist/react/tree.d.ts.map +1 -0
- package/dist/react/tree.js +37 -0
- package/dist/shared-words-BfnT24Fe.js +1635 -0
- package/dist/shared-words-BfnT24Fe.js.map +1 -0
- package/dist/shared-words-CyZYc_De.js +1818 -0
- package/dist/shared-words-CyZYc_De.js.map +1 -0
- package/dist/shared-words-DAVSET4Z.js +1800 -0
- package/dist/shared-words-DAVSET4Z.js.map +1 -0
- package/dist/shared-words-UCvnkctb.js +1653 -0
- package/dist/shared-words-UCvnkctb.js.map +1 -0
- package/package.json +16 -5
- package/DS1/2-core/ds-banner.ts +0 -122
- package/DS1/2-core/ds-date.ts +0 -24
- package/DS1/2-core/ds-language.ts +0 -94
- package/DS1/2-core/ds-pagedots.ts +0 -52
- package/DS1/2-core/ds-split.ts +0 -122
- package/DS1/2-core/ds-textarea.ts +0 -136
- package/DS1/2-core/styles/ds-banner.css +0 -77
- package/DS1/2-core/styles/ds-date.css +0 -9
- package/DS1/2-core/styles/ds-language.css +0 -78
- package/DS1/2-core/styles/ds-pagedots.css +0 -31
- package/DS1/2-core/styles/ds-textarea.css +0 -27
- package/DS1/4-page/ds-layout.ts +0 -949
- package/DS1/4-page/styles/ds-layout.css +0 -246
- package/DS1/react/split.ts +0 -42
- package/DS1/x-icon/ezo-accordion-chevron.svg +0 -11
- package/DS1/x-icon/ezo-account-close.svg +0 -1
- package/DS1/x-icon/ezo-android-screen-archive.svg +0 -4
- package/DS1/x-icon/ezo-android-screen-calendar.svg +0 -6
- package/DS1/x-icon/ezo-android-screen-camera.svg +0 -5
- package/DS1/x-icon/ezo-android-screen-check.svg +0 -3
- package/DS1/x-icon/ezo-android-screen-compose.svg +0 -4
- package/DS1/x-icon/ezo-android-screen-globe.svg +0 -1
- package/DS1/x-icon/ezo-android-screen-shared.svg +0 -5
- package/DS1/x-icon/ezo-android-screen-store.svg +0 -4
- package/DS1/x-icon/ezo-android-screen-views.svg +0 -4
- package/DS1/x-icon/ezo-android-screen-work.svg +0 -3
- package/DS1/x-icon/ezo-arrow-cursor.svg +0 -8
- package/DS1/x-icon/ezo-block-accordion.svg +0 -1
- package/DS1/x-icon/ezo-block-divider.svg +0 -1
- package/DS1/x-icon/ezo-block-group.svg +0 -1
- package/DS1/x-icon/ezo-block-image.svg +0 -1
- package/DS1/x-icon/ezo-block-section.svg +0 -1
- package/DS1/x-icon/ezo-block-table.svg +0 -1
- package/DS1/x-icon/ezo-code.svg +0 -14
- package/DS1/x-icon/ezo-down.svg +0 -3
- package/DS1/x-icon/ezo-figma-premium-star.svg +0 -5
- package/DS1/x-icon/ezo-item-button-complete.svg +0 -4
- package/DS1/x-icon/ezo-item-button-header.svg +0 -3
- package/DS1/x-icon/ezo-item-button-open.svg +0 -3
- package/DS1/x-icon/ezo-item-button-star.svg +0 -3
- package/DS1/x-icon/ezo-item-button-unheader.svg +0 -7
- package/DS1/x-icon/ezo-item-button-unstar.svg +0 -5
- package/DS1/x-icon/ezo-item-star.svg +0 -5
- package/DS1/x-icon/ezo-left.svg +0 -3
- package/DS1/x-icon/ezo-logo.svg +0 -1
- package/DS1/x-icon/ezo-mic.svg +0 -8
- package/DS1/x-icon/ezo-move-column.svg +0 -14
- package/DS1/x-icon/ezo-move-row.svg +0 -18
- package/DS1/x-icon/ezo-navigation-check.svg +0 -1
- package/DS1/x-icon/ezo-note-back.svg +0 -5
- package/DS1/x-icon/ezo-note-menu-complete.svg +0 -11
- package/DS1/x-icon/ezo-note-menu-delete.svg +0 -4
- package/DS1/x-icon/ezo-note-menu-duplicate.svg +0 -8
- package/DS1/x-icon/ezo-note-menu-note.svg +0 -5
- package/DS1/x-icon/ezo-note-menu-page.svg +0 -3
- package/DS1/x-icon/ezo-note-menu-star.svg +0 -5
- package/DS1/x-icon/ezo-note-menu-start.svg +0 -6
- package/DS1/x-icon/ezo-note-menu-stop.svg +0 -6
- package/DS1/x-icon/ezo-note-more.svg +0 -7
- package/DS1/x-icon/ezo-note-star.svg +0 -5
- package/DS1/x-icon/ezo-pattern-call-to-action.svg +0 -1
- package/DS1/x-icon/ezo-play.svg +0 -5
- package/DS1/x-icon/ezo-premium-star.svg +0 -5
- package/DS1/x-icon/ezo-setting-1xdots.svg +0 -13
- package/DS1/x-icon/ezo-setting-1xgrid.svg +0 -10
- package/DS1/x-icon/ezo-setting-1xlines.svg +0 -7
- package/DS1/x-icon/ezo-setting-2xdots.svg +0 -8
- package/DS1/x-icon/ezo-setting-2xgrid.svg +0 -8
- package/DS1/x-icon/ezo-setting-2xlines.svg +0 -6
- package/DS1/x-icon/ezo-setting-blank.svg +0 -5
- package/DS1/x-icon/ezo-store-chevron.svg +0 -1
- package/DS1/x-icon/ezo-upgrade-close.svg +0 -5
- package/DS1/x-icon/product-sources.json +0 -2557
- /package/DS1/x-icon/{ezo-password-visibility-see.svg → password-see.svg} +0 -0
- /package/DS1/x-icon/{ezo-password-visibility-unsee.svg → password-unsee.svg} +0 -0
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
// ds-stat.ts
|
|
2
|
+
// A figure with its label and a line for its change or caption, written in
|
|
3
|
+
// the current language through 0-face/format.ts. Drawn by 1-root/figures.css,
|
|
4
|
+
// the same classes a page without scripts writes.
|
|
5
|
+
|
|
6
|
+
import { LitElement, html, nothing, unsafeCSS } from "lit";
|
|
7
|
+
import { getText } from "../0-face/i18n";
|
|
8
|
+
import { define } from "../0-face/define";
|
|
9
|
+
import { figureCells, figureFormat, formatFigure, type FigureFormat, type FigureOptions } from "./figures";
|
|
10
|
+
import "./ds-icon";
|
|
11
|
+
import metrics from "../1-root/component-metrics.css?inline";
|
|
12
|
+
import figures from "../1-root/figures.css?inline";
|
|
13
|
+
import styles from "./styles/ds-stat.css?inline";
|
|
14
|
+
|
|
15
|
+
export type StatTone = "danger" | "warning";
|
|
16
|
+
const TONES: readonly StatTone[] = ["danger", "warning"];
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @element ds-stat
|
|
20
|
+
* @prop {string} label - What the figure is: a translation key, or literal words.
|
|
21
|
+
* @prop {number} value - The figure, written as `format` says in the current language.
|
|
22
|
+
* @prop {string} figure - Words in place of the value ("Incomplete"): a key, or literal words.
|
|
23
|
+
* @prop {"number" | "compact" | "percent" | "money"} format - How the value is written. Number by default.
|
|
24
|
+
* @prop {string} currency - The ISO 4217 code for money.
|
|
25
|
+
* @prop {boolean} minor - The money is counted in the currency's minor unit (cents).
|
|
26
|
+
* @prop {boolean} whole - Money in whole units only.
|
|
27
|
+
* @prop {number} digits - Decimals, at least and at most.
|
|
28
|
+
* @prop {number} change - A change, written with its sign and an up or down icon before the caption.
|
|
29
|
+
* @prop {"number" | "compact" | "percent" | "money"} changeFormat - How the change is written (`change-format`). The value's format by default; `percent` reads a fraction.
|
|
30
|
+
* @prop {"danger" | "warning"} changeTone - The change in that colour (`change-tone`), where the page knows which way is bad.
|
|
31
|
+
* @prop {string} caption - A line under the figure: a key, or literal words.
|
|
32
|
+
* @prop {string} icon - An icon from the library on its own square before the label.
|
|
33
|
+
* @prop {"danger" | "warning"} tone - The figure in that colour.
|
|
34
|
+
* @prop {boolean} cells - Draw each digit in a cell of one width, for a face whose digits differ in width.
|
|
35
|
+
* @prop {boolean} literal - Show `label`, `figure` and `caption` as written, never looked up.
|
|
36
|
+
*
|
|
37
|
+
* @slot label - The label, as inline content.
|
|
38
|
+
* @slot figure - The figure, when the page writes it itself.
|
|
39
|
+
* @slot - Anything that belongs between the figure and the caption, such as a `ds-meter`.
|
|
40
|
+
* @slot caption - The caption, as inline content.
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* <ds-stat label="Revenue" value="1234.5" format="money" currency="EUR" change="0.12" change-format="percent" caption="Since last month"></ds-stat>
|
|
44
|
+
*/
|
|
45
|
+
export class Stat extends LitElement {
|
|
46
|
+
static properties = {
|
|
47
|
+
label: { type: String },
|
|
48
|
+
value: { type: Number },
|
|
49
|
+
figure: { type: String },
|
|
50
|
+
format: { type: String, reflect: true },
|
|
51
|
+
currency: { type: String },
|
|
52
|
+
minor: { type: Boolean },
|
|
53
|
+
whole: { type: Boolean },
|
|
54
|
+
digits: { type: Number },
|
|
55
|
+
change: { type: Number },
|
|
56
|
+
changeFormat: { type: String, attribute: "change-format" },
|
|
57
|
+
changeTone: { type: String, attribute: "change-tone", reflect: true },
|
|
58
|
+
caption: { type: String },
|
|
59
|
+
icon: { type: String },
|
|
60
|
+
tone: { type: String, reflect: true },
|
|
61
|
+
cells: { type: Boolean, reflect: true },
|
|
62
|
+
literal: { type: Boolean, reflect: true },
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
static styles = [unsafeCSS(metrics), unsafeCSS(figures), unsafeCSS(styles)];
|
|
66
|
+
|
|
67
|
+
declare label: string | undefined;
|
|
68
|
+
declare value: number | undefined;
|
|
69
|
+
declare figure: string | undefined;
|
|
70
|
+
declare format: FigureFormat;
|
|
71
|
+
declare currency: string | undefined;
|
|
72
|
+
declare minor: boolean;
|
|
73
|
+
declare whole: boolean;
|
|
74
|
+
declare digits: number | undefined;
|
|
75
|
+
declare change: number | undefined;
|
|
76
|
+
declare changeFormat: FigureFormat | undefined;
|
|
77
|
+
declare changeTone: StatTone | undefined;
|
|
78
|
+
declare caption: string | undefined;
|
|
79
|
+
declare icon: string | undefined;
|
|
80
|
+
declare tone: StatTone | undefined;
|
|
81
|
+
declare cells: boolean;
|
|
82
|
+
declare literal: boolean;
|
|
83
|
+
|
|
84
|
+
private readonly relabel = () => this.requestUpdate();
|
|
85
|
+
|
|
86
|
+
constructor() {
|
|
87
|
+
super();
|
|
88
|
+
this.format = "number";
|
|
89
|
+
this.minor = false;
|
|
90
|
+
this.whole = false;
|
|
91
|
+
this.cells = false;
|
|
92
|
+
this.literal = false;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
connectedCallback() {
|
|
96
|
+
super.connectedCallback();
|
|
97
|
+
window.addEventListener("language-changed", this.relabel);
|
|
98
|
+
window.addEventListener("translations-loaded", this.relabel);
|
|
99
|
+
window.addEventListener("translations-ready", this.relabel);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
disconnectedCallback() {
|
|
103
|
+
window.removeEventListener("language-changed", this.relabel);
|
|
104
|
+
window.removeEventListener("translations-loaded", this.relabel);
|
|
105
|
+
window.removeEventListener("translations-ready", this.relabel);
|
|
106
|
+
super.disconnectedCallback();
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
private words(value: string | undefined): string {
|
|
110
|
+
if (!value) return "";
|
|
111
|
+
return this.literal ? value : getText(value) || value;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
private options(format: string | undefined): FigureOptions {
|
|
115
|
+
return { format: figureFormat(format), currency: this.currency, minor: this.minor, whole: this.whole, digits: this.digits };
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/** The figure's text as it is drawn: the words given, or the value written in the current language. */
|
|
119
|
+
get text(): string {
|
|
120
|
+
if (this.figure) return this.words(this.figure);
|
|
121
|
+
return typeof this.value === "number" ? formatFigure(this.value, this.options(this.format)) : "";
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/** The change's text with its sign, or empty without a change. */
|
|
125
|
+
get changeText(): string {
|
|
126
|
+
if (typeof this.change !== "number" || !Number.isFinite(this.change)) return "";
|
|
127
|
+
const format = this.changeFormat ?? this.format;
|
|
128
|
+
return formatFigure(this.change, { ...this.options(format), signed: true });
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
private slotted(name: string): boolean {
|
|
132
|
+
return [...this.children].some(node => (node.getAttribute("slot") ?? "") === name);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
private drawFigure(text: string) {
|
|
136
|
+
if (!this.cells || !text) return text;
|
|
137
|
+
return html`<span class="hidden-words">${text}</span><span aria-hidden="true">${figureCells(text).map(cell =>
|
|
138
|
+
cell.digit ? html`<span class="ds-stat__digit">${cell.text}</span>` : cell.text)}</span>`;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
render() {
|
|
142
|
+
const changed = () => this.requestUpdate();
|
|
143
|
+
const label = this.words(this.label);
|
|
144
|
+
const caption = this.words(this.caption);
|
|
145
|
+
const change = this.changeText;
|
|
146
|
+
const tone = TONES.includes(this.tone as StatTone) ? this.tone : undefined;
|
|
147
|
+
const changeTone = TONES.includes(this.changeTone as StatTone) ? this.changeTone : undefined;
|
|
148
|
+
const hasLabel = Boolean(label) || this.slotted("label");
|
|
149
|
+
const hasCaption = Boolean(caption) || Boolean(change) || this.slotted("caption");
|
|
150
|
+
const direction = typeof this.change === "number" && this.change !== 0 ? (this.change > 0 ? "up" : "down") : undefined;
|
|
151
|
+
return html`<div class="ds-stat${tone ? ` ds-stat--${tone}` : ""}" part="stat">
|
|
152
|
+
<div class="ds-stat__label" part="label" ?hidden=${!hasLabel}>
|
|
153
|
+
${this.icon ? html`<span class="ds-stat__icon" part="icon" aria-hidden="true"><ds-icon .type=${this.icon}></ds-icon></span>` : nothing}<slot name="label" @slotchange=${changed}>${label}</slot>
|
|
154
|
+
</div>
|
|
155
|
+
<div class="ds-stat__figure" part="figure"><slot name="figure" @slotchange=${changed}>${this.drawFigure(this.text)}</slot></div>
|
|
156
|
+
<slot></slot>
|
|
157
|
+
<div class="ds-stat__caption" part="caption" ?hidden=${!hasCaption}>
|
|
158
|
+
${change
|
|
159
|
+
? html`<span class="ds-stat__change${changeTone ? ` ds-stat__change--${changeTone}` : ""}" part="change">${direction
|
|
160
|
+
? html`<ds-icon size="small" type=${direction} aria-hidden="true"></ds-icon>`
|
|
161
|
+
: nothing}${change}</span>`
|
|
162
|
+
: nothing}<slot name="caption" @slotchange=${changed}>${caption}</slot>
|
|
163
|
+
</div>
|
|
164
|
+
</div>`;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
define("ds-stat", Stat);
|
|
169
|
+
|
|
170
|
+
declare global {
|
|
171
|
+
interface HTMLElementTagNameMap {
|
|
172
|
+
"ds-stat": Stat;
|
|
173
|
+
}
|
|
174
|
+
}
|
package/DS1/2-core/ds-switch.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { define } from "../0-face/define";
|
|
|
3
3
|
import styles from "./styles/ds-switch.css?inline";
|
|
4
4
|
|
|
5
5
|
/** The shared switch face. The slotted button retains native activation and refs. */
|
|
6
|
+
/** rounded selects a pill track, white circular thumb and darker-green on state. */
|
|
6
7
|
export class Switch extends LitElement {
|
|
7
8
|
static styles = unsafeCSS(styles);
|
|
8
9
|
focus(options?: FocusOptions) { this.querySelector<HTMLButtonElement>(":scope > button")?.focus(options); }
|
package/DS1/2-core/ds-text.ts
CHANGED
|
@@ -10,6 +10,16 @@ import styles from "./styles/ds-text.css?inline";
|
|
|
10
10
|
* @prop {string} text - The translation key (optional if using slot content)
|
|
11
11
|
* @prop {boolean} literal - The text is what someone wrote, not a key: show it
|
|
12
12
|
* as it stands, never looked up, never translated
|
|
13
|
+
* @prop {"muted" | "title" | "warning" | "danger"} tone - A quieter colour, the
|
|
14
|
+
* title grey, the warning colour for something that needs care, or the
|
|
15
|
+
* danger colour for a failure or a loss
|
|
16
|
+
* @prop {"small" | "heading" | "display"} size - 10px, a 13px heading on one
|
|
17
|
+
* square, or a 20px title on two squares
|
|
18
|
+
* @prop {boolean} strong - The medium weight
|
|
19
|
+
* @prop {boolean} wrap - Let the text run over several lines, each one square
|
|
20
|
+
*
|
|
21
|
+
* The four work alike for a translation key and for literal text. For a
|
|
22
|
+
* heading, give the element `role="heading"` and `aria-level`.
|
|
13
23
|
*
|
|
14
24
|
* @example
|
|
15
25
|
* // Using slot content as the key (preferred)
|
|
@@ -20,6 +30,9 @@ import styles from "./styles/ds-text.css?inline";
|
|
|
20
30
|
*
|
|
21
31
|
* // Something a person typed: a list title, an item, a search they saved
|
|
22
32
|
* <ds-text literal text="Marketing plan"></ds-text>
|
|
33
|
+
*
|
|
34
|
+
* // A translated message over several lines, in the danger colour
|
|
35
|
+
* <ds-text wrap tone="danger" role="alert">Couldn't save your changes</ds-text>
|
|
23
36
|
*/
|
|
24
37
|
export class Text extends LitElement {
|
|
25
38
|
static get properties() {
|
|
@@ -36,8 +49,8 @@ export class Text extends LitElement {
|
|
|
36
49
|
|
|
37
50
|
declare text: string;
|
|
38
51
|
declare literal: boolean;
|
|
39
|
-
declare tone?: "muted" | "title";
|
|
40
|
-
declare size?: "small" | "heading";
|
|
52
|
+
declare tone?: "muted" | "title" | "warning" | "danger";
|
|
53
|
+
declare size?: "small" | "heading" | "display";
|
|
41
54
|
declare strong: boolean;
|
|
42
55
|
declare wrap: boolean;
|
|
43
56
|
declare _text: string;
|
|
@@ -0,0 +1,354 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Toast: short messages that stack in a corner of the page and leave on their own.
|
|
3
|
+
*
|
|
4
|
+
* BASED ON SONNER. This component is a Lit port of Sonner, the React toast
|
|
5
|
+
* library by Emil Kowalski (https://sonner.emilkowal.ski,
|
|
6
|
+
* https://github.com/emilkowalski/sonner, MIT licence). Its API and behaviour
|
|
7
|
+
* follow Sonner's, so Sonner's documentation describes how it works:
|
|
8
|
+
*
|
|
9
|
+
* - `toast()`, `toast.success()`, `.info()`, `.warning()`, `.error()`,
|
|
10
|
+
* `.loading()`, `.message()`, `.promise()` and `.dismiss()` are Sonner's calls,
|
|
11
|
+
* with Sonner's options (`id`, `description`, `duration`, `action`, `cancel`,
|
|
12
|
+
* `dismissible`, `closeButton`, `important`, `onDismiss`, `onAutoClose`).
|
|
13
|
+
* - `<ds-toast>` is Sonner's `<Toaster />`, with its `position`, `expand`,
|
|
14
|
+
* `visible-toasts`, `duration`, `close-button` and `rich-colors`;
|
|
15
|
+
* `contained` draws it inside its positioned parent instead of the window.
|
|
16
|
+
* - A toast stays 4 seconds; its timer pauses while the stack is hovered,
|
|
17
|
+
* focused, held or the tab is hidden. Three show at once, stacked behind
|
|
18
|
+
* one another and spread out on hover. A swipe towards the edge dismisses one,
|
|
19
|
+
* Alt+T reaches them from the keyboard, and they come and go with Sonner's
|
|
20
|
+
* 400ms slide and fade.
|
|
21
|
+
*
|
|
22
|
+
* Where it departs from Sonner, it follows Design system 1: a toast is drawn as
|
|
23
|
+
* the system's label, an ink chip one control high per line in the tooltip's
|
|
24
|
+
* colours, with no line or shadow, its actions underlined words; the pile
|
|
25
|
+
* advances one square per toast, one square from the edge. Only `transform`
|
|
26
|
+
* and `opacity` animate (a toast stacked behind takes the front one's height at
|
|
27
|
+
* once instead of animating it). `toast()` also adds a `<ds-toast>` to the page
|
|
28
|
+
* when there is none, and moving the element keeps its toasts and their time.
|
|
29
|
+
* An error is announced assertively unless it says `important: false`.
|
|
30
|
+
*
|
|
31
|
+
* `toast()` and its queue are framework-free (`0-face/toast-queue.ts`). On a
|
|
32
|
+
* page without Lit, the page toaster (`0-face/toaster.ts`) draws the same stack
|
|
33
|
+
* with this component's stylesheet; where a `<ds-toast>` is in the page, it
|
|
34
|
+
* takes every toast, so a page never shows two stacks.
|
|
35
|
+
*/
|
|
36
|
+
import { LitElement, html, nothing, unsafeCSS } from "lit";
|
|
37
|
+
import { repeat } from "lit/directives/repeat.js";
|
|
38
|
+
import { define } from "../0-face/define";
|
|
39
|
+
import {
|
|
40
|
+
SWIPE_THRESHOLD,
|
|
41
|
+
SWIPE_VELOCITY,
|
|
42
|
+
TIME_BEFORE_UNMOUNT,
|
|
43
|
+
TOAST_DURATION as DURATION,
|
|
44
|
+
TOAST_ICONS as ICONS,
|
|
45
|
+
VISIBLE_TOASTS,
|
|
46
|
+
listenForToasts,
|
|
47
|
+
} from "../0-face/toast-queue";
|
|
48
|
+
import type { ToastButton, ToastData, ToastId, ToastPosition, ToastSignal as Signal } from "../0-face/toast-queue";
|
|
49
|
+
import "./ds-icon";
|
|
50
|
+
import styles from "./styles/ds-toast.css?inline";
|
|
51
|
+
|
|
52
|
+
/* Sonner's calls and their queue are framework-free (`0-face/toast-queue.ts`), shared with the page toaster. */
|
|
53
|
+
export { toast } from "../0-face/toast-queue";
|
|
54
|
+
export type { ToastButton, ToastData, ToastId, ToastOptions, ToastPosition, ToastPromiseMessages, ToastType } from "../0-face/toast-queue";
|
|
55
|
+
|
|
56
|
+
interface Item { data: ToastData; mounted: boolean; removed: boolean; swipeOut: boolean; index: number; offset: number }
|
|
57
|
+
interface Timer { remaining: number; started: number; handle?: ReturnType<typeof setTimeout> }
|
|
58
|
+
|
|
59
|
+
/** The region that shows the toasts, Sonner's `<Toaster />`. Put one in the page. */
|
|
60
|
+
export class Toaster extends LitElement {
|
|
61
|
+
static properties = {
|
|
62
|
+
position: { type: String, reflect: true },
|
|
63
|
+
expand: { type: Boolean, reflect: true },
|
|
64
|
+
visibleToasts: { type: Number, attribute: "visible-toasts" },
|
|
65
|
+
duration: { type: Number },
|
|
66
|
+
closeButton: { type: Boolean, attribute: "close-button" },
|
|
67
|
+
richColors: { type: Boolean, attribute: "rich-colors", reflect: true },
|
|
68
|
+
contained: { type: Boolean, reflect: true },
|
|
69
|
+
label: { type: String },
|
|
70
|
+
closeLabel: { type: String, attribute: "close-label" },
|
|
71
|
+
_items: { state: true },
|
|
72
|
+
_hovered: { state: true },
|
|
73
|
+
_focused: { state: true },
|
|
74
|
+
};
|
|
75
|
+
static styles = unsafeCSS(styles);
|
|
76
|
+
|
|
77
|
+
declare position: ToastPosition;
|
|
78
|
+
declare expand: boolean;
|
|
79
|
+
declare visibleToasts: number;
|
|
80
|
+
declare duration: number;
|
|
81
|
+
declare closeButton: boolean;
|
|
82
|
+
declare richColors: boolean;
|
|
83
|
+
/** Draw within the nearest positioned ancestor instead of the window. */
|
|
84
|
+
declare contained: boolean;
|
|
85
|
+
/** The region's accessible name; products pass their own words. */
|
|
86
|
+
declare label: string;
|
|
87
|
+
declare closeLabel: string;
|
|
88
|
+
declare private _items: Item[];
|
|
89
|
+
declare private _hovered: boolean;
|
|
90
|
+
declare private _focused: boolean;
|
|
91
|
+
private heights = new Map<ToastId, number>();
|
|
92
|
+
private timers = new Map<ToastId, Timer>();
|
|
93
|
+
private interacting = false;
|
|
94
|
+
private swipe?: { id: ToastId; start: number; time: number; amount: number };
|
|
95
|
+
private resizes = typeof ResizeObserver === "undefined" ? undefined : new ResizeObserver(() => this.measure());
|
|
96
|
+
private stopListening?: () => void;
|
|
97
|
+
|
|
98
|
+
constructor() {
|
|
99
|
+
super();
|
|
100
|
+
this.position = "bottom-right";
|
|
101
|
+
this.expand = false;
|
|
102
|
+
this.visibleToasts = VISIBLE_TOASTS;
|
|
103
|
+
this.duration = DURATION;
|
|
104
|
+
this.closeButton = false;
|
|
105
|
+
this.richColors = false;
|
|
106
|
+
this.contained = false;
|
|
107
|
+
this.label = "Notifications";
|
|
108
|
+
this.closeLabel = "Close toast";
|
|
109
|
+
this._items = [];
|
|
110
|
+
this._hovered = false;
|
|
111
|
+
this._focused = false;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
connectedCallback(): void {
|
|
115
|
+
super.connectedCallback();
|
|
116
|
+
this.stopListening?.();
|
|
117
|
+
this.stopListening = listenForToasts(this.receive);
|
|
118
|
+
document.addEventListener("keydown", this.hotkey);
|
|
119
|
+
document.addEventListener("visibilitychange", this.syncTimers);
|
|
120
|
+
// Moved to another parent: carry on with the time each toast had left.
|
|
121
|
+
this.requestUpdate();
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
disconnectedCallback(): void {
|
|
125
|
+
super.disconnectedCallback();
|
|
126
|
+
this.stopListening?.();
|
|
127
|
+
this.stopListening = undefined;
|
|
128
|
+
document.removeEventListener("keydown", this.hotkey);
|
|
129
|
+
document.removeEventListener("visibilitychange", this.syncTimers);
|
|
130
|
+
const now = Date.now();
|
|
131
|
+
for (const timer of this.timers.values()) {
|
|
132
|
+
if (timer.handle === undefined) continue;
|
|
133
|
+
clearTimeout(timer.handle);
|
|
134
|
+
timer.handle = undefined;
|
|
135
|
+
timer.remaining -= now - timer.started;
|
|
136
|
+
}
|
|
137
|
+
this.resizes?.disconnect();
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
private get live(): Item[] { return this._items.filter(item => !item.removed); }
|
|
141
|
+
private get expanded(): boolean { return this.expand || ((this._hovered || this._focused) && this.live.length > 0); }
|
|
142
|
+
private get paused(): boolean { return this._hovered || this._focused || this.interacting || document.hidden; }
|
|
143
|
+
|
|
144
|
+
private receive = (signal: Signal) => {
|
|
145
|
+
if ("dismiss" in signal) {
|
|
146
|
+
for (const item of this.live) if (signal.dismiss === undefined || item.data.id === signal.dismiss) this.removeToast(item.data.id);
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
const data = signal.toast;
|
|
150
|
+
const current = this.live.find(item => item.data.id === data.id);
|
|
151
|
+
if (current) {
|
|
152
|
+
// An update keeps what it does not change and starts its time again, as in Sonner.
|
|
153
|
+
this._items = this._items.map(item => item === current ? { ...item, data: { ...item.data, ...data } } : item);
|
|
154
|
+
this.clearTimer(data.id);
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
this._items = [{ data, mounted: false, removed: false, swipeOut: false, index: 0, offset: 0 }, ...this._items.filter(item => item.data.id !== data.id)];
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
private removeToast(id: ToastId, how: "dismiss" | "auto" | "swipe" = "dismiss") {
|
|
161
|
+
const item = this.live.find(entry => entry.data.id === id);
|
|
162
|
+
if (!item) return;
|
|
163
|
+
this.clearTimer(id);
|
|
164
|
+
this.heights.delete(id);
|
|
165
|
+
(how === "auto" ? item.data.onAutoClose : item.data.onDismiss)?.(item.data);
|
|
166
|
+
const removed = { ...item, removed: true, swipeOut: how === "swipe" };
|
|
167
|
+
this._items = this._items.map(entry => entry === item ? removed : entry);
|
|
168
|
+
setTimeout(() => { this._items = this._items.filter(entry => entry !== removed); }, TIME_BEFORE_UNMOUNT);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
private clearTimer(id: ToastId) {
|
|
172
|
+
clearTimeout(this.timers.get(id)?.handle);
|
|
173
|
+
this.timers.delete(id);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/** Sonner's timers: each toast keeps its remaining time while the stack is paused. */
|
|
177
|
+
private syncTimers = () => {
|
|
178
|
+
const now = Date.now();
|
|
179
|
+
for (const item of this.live) {
|
|
180
|
+
const { id, type } = item.data;
|
|
181
|
+
const duration = item.data.duration ?? this.duration;
|
|
182
|
+
if (type === "loading" || duration === Infinity) { this.clearTimer(id); continue; }
|
|
183
|
+
let timer = this.timers.get(id);
|
|
184
|
+
if (!timer) { timer = { remaining: duration, started: now }; this.timers.set(id, timer); }
|
|
185
|
+
if (this.paused && timer.handle !== undefined) {
|
|
186
|
+
clearTimeout(timer.handle);
|
|
187
|
+
timer.handle = undefined;
|
|
188
|
+
timer.remaining -= now - timer.started;
|
|
189
|
+
} else if (!this.paused && timer.handle === undefined) {
|
|
190
|
+
timer.started = now;
|
|
191
|
+
timer.handle = setTimeout(() => this.removeToast(id, "auto"), Math.max(0, timer.remaining));
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
private hotkey = (event: KeyboardEvent) => {
|
|
197
|
+
const list = this.renderRoot.querySelector("ol");
|
|
198
|
+
if (event.altKey && event.code === "KeyT" && this.live.length) {
|
|
199
|
+
this._focused = true;
|
|
200
|
+
list?.focus();
|
|
201
|
+
} else if (event.key === "Escape" && this._focused) {
|
|
202
|
+
this._focused = false;
|
|
203
|
+
}
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
private onFocusOut = (event: FocusEvent) => {
|
|
207
|
+
if (!(event.relatedTarget instanceof Node && this.renderRoot.contains(event.relatedTarget))) this._focused = false;
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
private measure() {
|
|
211
|
+
let changed = false;
|
|
212
|
+
for (const body of this.renderRoot.querySelectorAll<HTMLElement>(".body")) {
|
|
213
|
+
const id = this._items.find(item => String(item.data.id) === body.dataset.id && !item.removed)?.data.id;
|
|
214
|
+
if (id === undefined) continue;
|
|
215
|
+
const toast = body.parentElement!;
|
|
216
|
+
const height = body.offsetHeight + toast.offsetHeight - toast.clientHeight;
|
|
217
|
+
if (this.heights.get(id) !== height) { this.heights.set(id, height); changed = true; }
|
|
218
|
+
}
|
|
219
|
+
if (changed) this.requestUpdate();
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
protected updated(): void {
|
|
223
|
+
for (const body of this.renderRoot.querySelectorAll<HTMLElement>(".body")) this.resizes?.observe(body);
|
|
224
|
+
this.measure();
|
|
225
|
+
if (!this.live.length) { this._hovered = false; this._focused = false; }
|
|
226
|
+
this.syncTimers();
|
|
227
|
+
if (this._items.some(item => !item.mounted)) {
|
|
228
|
+
// Mount on the next frame so the toast slides in from its edge.
|
|
229
|
+
const frame = typeof requestAnimationFrame === "function" ? requestAnimationFrame : (callback: () => void) => setTimeout(callback, 16);
|
|
230
|
+
frame(() => { this._items = this._items.map(item => item.mounted ? item : { ...item, mounted: true }); });
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
private onPointerDown(event: PointerEvent, item: Item) {
|
|
235
|
+
if (item.data.dismissible === false || item.data.type === "loading") return;
|
|
236
|
+
if ((event.composedPath()[0] as Element | undefined)?.closest?.("button, a")) return;
|
|
237
|
+
(event.currentTarget as HTMLElement).setPointerCapture?.(event.pointerId);
|
|
238
|
+
this.swipe = { id: item.data.id, start: event.clientY, time: Date.now(), amount: 0 };
|
|
239
|
+
this.interacting = true;
|
|
240
|
+
this.syncTimers();
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
private onPointerMove = (event: PointerEvent) => {
|
|
244
|
+
if (!this.swipe) return;
|
|
245
|
+
const toward = this.position.startsWith("top") ? -1 : 1;
|
|
246
|
+
// Only towards the edge the toast came from.
|
|
247
|
+
this.swipe.amount = Math.max(0, (event.clientY - this.swipe.start) * toward);
|
|
248
|
+
const element = event.currentTarget as HTMLElement;
|
|
249
|
+
element.dataset.swiping = "true";
|
|
250
|
+
element.style.setProperty("--swipe", `${this.swipe.amount * toward}px`);
|
|
251
|
+
};
|
|
252
|
+
|
|
253
|
+
private onPointerUp = (event: PointerEvent) => {
|
|
254
|
+
const swipe = this.swipe;
|
|
255
|
+
if (!swipe) return;
|
|
256
|
+
this.swipe = undefined;
|
|
257
|
+
this.interacting = false;
|
|
258
|
+
const element = event.currentTarget as HTMLElement;
|
|
259
|
+
delete element.dataset.swiping;
|
|
260
|
+
const velocity = swipe.amount / Math.max(1, Date.now() - swipe.time);
|
|
261
|
+
if (swipe.amount >= SWIPE_THRESHOLD || velocity > SWIPE_VELOCITY) this.removeToast(swipe.id, "swipe");
|
|
262
|
+
else element.style.setProperty("--swipe", "0px");
|
|
263
|
+
this.syncTimers();
|
|
264
|
+
};
|
|
265
|
+
|
|
266
|
+
private press(event: MouseEvent, item: Item, button: ToastButton) {
|
|
267
|
+
button.onClick?.(event);
|
|
268
|
+
if (button.href) this.removeToast(item.data.id);
|
|
269
|
+
else if (!event.defaultPrevented) this.removeToast(item.data.id);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
private renderButton(item: Item, button: ToastButton, kind: "cancel" | "action") {
|
|
273
|
+
const press = (event: MouseEvent) => this.press(event, item, button);
|
|
274
|
+
return button.href
|
|
275
|
+
? html`<a class=${`button ${kind}`} href=${button.href} @click=${press}>${button.label}</a>`
|
|
276
|
+
: html`<button class=${`button ${kind}`} type="button" @click=${press}>${button.label}</button>`;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
private renderIcon(data: ToastData) {
|
|
280
|
+
if (data.type === "loading") return html`<span class="icon" aria-hidden="true"><span class="spinner"></span></span>`;
|
|
281
|
+
const icon = data.icon ?? ICONS[data.type];
|
|
282
|
+
return icon ? html`<span class="icon" aria-hidden="true"><ds-icon .type=${icon}></ds-icon></span>` : nothing;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
private renderToast(item: Item, count: number, frontHeight: number) {
|
|
286
|
+
const { data } = item;
|
|
287
|
+
const dismissible = data.dismissible !== false;
|
|
288
|
+
const closeButton = (data.closeButton ?? this.closeButton) && dismissible;
|
|
289
|
+
return html`<li
|
|
290
|
+
class="toast"
|
|
291
|
+
role="status"
|
|
292
|
+
tabindex="0"
|
|
293
|
+
aria-live=${data.important ? "assertive" : "polite"}
|
|
294
|
+
aria-atomic="true"
|
|
295
|
+
data-type=${data.type}
|
|
296
|
+
data-front=${String(item.index === 0)}
|
|
297
|
+
data-mounted=${String(item.mounted)}
|
|
298
|
+
data-removed=${String(item.removed)}
|
|
299
|
+
data-swipe-out=${String(item.swipeOut)}
|
|
300
|
+
data-visible=${String(item.index < this.visibleToasts)}
|
|
301
|
+
style=${`--index: ${item.index}; --offset: ${item.offset}px; --front-height: ${frontHeight}px; z-index: ${count - item.index}`}
|
|
302
|
+
@pointerdown=${(event: PointerEvent) => this.onPointerDown(event, item)}
|
|
303
|
+
@pointermove=${this.onPointerMove}
|
|
304
|
+
@pointerup=${this.onPointerUp}
|
|
305
|
+
@pointercancel=${this.onPointerUp}
|
|
306
|
+
>
|
|
307
|
+
<div class="body" data-id=${String(data.id)}>
|
|
308
|
+
${this.renderIcon(data)}
|
|
309
|
+
<div class="content">
|
|
310
|
+
<div class="title">${data.title}</div>
|
|
311
|
+
${data.description ? html`<div class="description">${data.description}</div>` : nothing}
|
|
312
|
+
</div>
|
|
313
|
+
${data.cancel ? this.renderButton(item, data.cancel, "cancel") : nothing}
|
|
314
|
+
${data.action ? this.renderButton(item, data.action, "action") : nothing}
|
|
315
|
+
${closeButton ? html`<button class="close" type="button" aria-label=${this.closeLabel} @click=${() => this.removeToast(data.id)}><ds-icon type="close"></ds-icon></button>` : nothing}
|
|
316
|
+
</div>
|
|
317
|
+
</li>`;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
render() {
|
|
321
|
+
// Index and offset count live toasts only; one leaving keeps where it was.
|
|
322
|
+
let offset = 0;
|
|
323
|
+
this.live.forEach((item, index) => {
|
|
324
|
+
item.index = index;
|
|
325
|
+
item.offset = offset;
|
|
326
|
+
offset += this.heights.get(item.data.id) ?? 0;
|
|
327
|
+
});
|
|
328
|
+
const live = this.live;
|
|
329
|
+
const frontHeight = live.length ? this.heights.get(live[0]!.data.id) ?? 0 : 0;
|
|
330
|
+
const gaps = Math.max(0, live.length - 1);
|
|
331
|
+
const [y, x] = this.position.split("-") as ["top" | "bottom", "left" | "center" | "right"];
|
|
332
|
+
return html`<section aria-label=${`${this.label} alt+T`} aria-live="polite" aria-relevant="additions text" aria-atomic="false">
|
|
333
|
+
<ol
|
|
334
|
+
tabindex="-1"
|
|
335
|
+
data-y=${y}
|
|
336
|
+
data-x=${x}
|
|
337
|
+
data-expanded=${String(this.expanded)}
|
|
338
|
+
style=${`--height: ${this.expanded ? offset : frontHeight}px; --gaps: ${this.expanded ? gaps : 0}`}
|
|
339
|
+
@pointerenter=${() => { this._hovered = true; }}
|
|
340
|
+
@pointerleave=${() => { if (!this.interacting) this._hovered = false; }}
|
|
341
|
+
@focusin=${() => { this._focused = true; }}
|
|
342
|
+
@focusout=${this.onFocusOut}
|
|
343
|
+
>
|
|
344
|
+
${repeat(this._items, item => item.data.id, item => this.renderToast(item, this._items.length, frontHeight))}
|
|
345
|
+
</ol>
|
|
346
|
+
</section>`;
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
define("ds-toast", Toaster);
|
|
351
|
+
|
|
352
|
+
declare global {
|
|
353
|
+
interface HTMLElementTagNameMap { "ds-toast": Toaster }
|
|
354
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
// figures.ts
|
|
2
|
+
// The words of a figure, shared by ds-stat, ds-progress and their React
|
|
3
|
+
// adapters: a value written through 0-face/format.ts in the current language,
|
|
4
|
+
// the digits cut into cells of one width, and a meter's ARIA values. No
|
|
5
|
+
// browser code, so the adapters write the same words on the server.
|
|
6
|
+
|
|
7
|
+
import { formatCompact, formatMoney, formatNumber, formatPercent } from "../0-face/format";
|
|
8
|
+
import { translate } from "../0-face/i18n";
|
|
9
|
+
|
|
10
|
+
/** How a figure's value is written: a number, a short number (12K), a fraction as a percentage, or money. */
|
|
11
|
+
export type FigureFormat = "number" | "compact" | "percent" | "money";
|
|
12
|
+
const FORMATS: readonly FigureFormat[] = ["number", "compact", "percent", "money"];
|
|
13
|
+
|
|
14
|
+
export interface FigureOptions {
|
|
15
|
+
/** `number` by default. `money` needs `currency`; without one it writes a number. */
|
|
16
|
+
format?: FigureFormat;
|
|
17
|
+
/** An ISO 4217 code for `money`: `USD`, `DKK`, `JPY`. */
|
|
18
|
+
currency?: string;
|
|
19
|
+
/** For money: the amount is in the currency's minor unit (cents, øre). */
|
|
20
|
+
minor?: boolean;
|
|
21
|
+
/** For money: whole units only, rounded. */
|
|
22
|
+
whole?: boolean;
|
|
23
|
+
/** Decimals, at least and at most. Unset, the format's own (none for a percentage, the currency's for money). */
|
|
24
|
+
digits?: number;
|
|
25
|
+
/** Write a sign before a value that is not zero: `+12%`, `−3`. */
|
|
26
|
+
signed?: boolean;
|
|
27
|
+
/** Format in this language rather than the current one. */
|
|
28
|
+
language?: string;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** A format name as given, or `number` for one this does not know. */
|
|
32
|
+
export function figureFormat(value: string | null | undefined): FigureFormat {
|
|
33
|
+
return FORMATS.includes(value as FigureFormat) ? (value as FigureFormat) : "number";
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** A value written as `options` say, in the current language: `1,234`, `12K`, `25%`, `$1,234.50`, `+12%`. */
|
|
37
|
+
export function formatFigure(value: number, options: FigureOptions = {}): string {
|
|
38
|
+
if (!Number.isFinite(value)) return "";
|
|
39
|
+
const { currency, minor, whole, digits, signed, language } = options;
|
|
40
|
+
const format = figureFormat(options.format);
|
|
41
|
+
const numeric: Intl.NumberFormatOptions & { language?: string } = { language };
|
|
42
|
+
if (signed) numeric.signDisplay = "exceptZero";
|
|
43
|
+
if (digits !== undefined && Number.isFinite(digits) && digits >= 0) {
|
|
44
|
+
numeric.minimumFractionDigits = Math.min(20, Math.floor(digits));
|
|
45
|
+
numeric.maximumFractionDigits = Math.min(20, Math.floor(digits));
|
|
46
|
+
}
|
|
47
|
+
if (format === "money" && currency) return formatMoney(value, currency, { ...numeric, minor, whole });
|
|
48
|
+
if (format === "percent") return formatPercent(value, numeric);
|
|
49
|
+
if (format === "compact") return formatCompact(value, numeric);
|
|
50
|
+
return formatNumber(value, numeric);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** A run of a figure's text: a digit, which takes a cell of its own, or the signs and letters between. */
|
|
54
|
+
export interface FigureCell { text: string; digit: boolean }
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* A figure's text cut into its digits and the runs between them, for a face
|
|
58
|
+
* whose digits are not all one width: each digit is drawn in a cell of one
|
|
59
|
+
* width (`ds-stat__digit`), the rest at its own. The text is read whole.
|
|
60
|
+
*/
|
|
61
|
+
export function figureCells(text: string): FigureCell[] {
|
|
62
|
+
const cells: FigureCell[] = [];
|
|
63
|
+
for (const character of text) {
|
|
64
|
+
const digit = /\p{Nd}/u.test(character);
|
|
65
|
+
const last = cells[cells.length - 1];
|
|
66
|
+
if (!digit && last && !last.digit) last.text += character;
|
|
67
|
+
else cells.push({ text: character, digit });
|
|
68
|
+
}
|
|
69
|
+
return cells;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/** What a meter says to assistive technology. */
|
|
73
|
+
export interface MeterAria {
|
|
74
|
+
/** The value, kept inside the range as ARIA requires. */
|
|
75
|
+
now: number;
|
|
76
|
+
min: number;
|
|
77
|
+
max: number;
|
|
78
|
+
/** "7 of 10", or "12 of 10, over by 2", in the current language. */
|
|
79
|
+
text: string;
|
|
80
|
+
/** How much of the range is filled, 0 to 1. */
|
|
81
|
+
fraction: number;
|
|
82
|
+
/** The value is past the end of the range. */
|
|
83
|
+
over: boolean;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* A meter's values: the value kept inside `min` and `max`, how much of the
|
|
88
|
+
* range it fills, whether it is past the end, and the words that say so, the
|
|
89
|
+
* figures written as `options` say. A range that is empty or backwards reads
|
|
90
|
+
* as 0 to 1.
|
|
91
|
+
*/
|
|
92
|
+
export function meterAria(value: number, min = 0, max = 1, options: FigureOptions & { over?: boolean } = {}): MeterAria {
|
|
93
|
+
const low = Number.isFinite(min) ? min : 0;
|
|
94
|
+
const high = Number.isFinite(max) && max > low ? max : low + 1;
|
|
95
|
+
const raw = Number.isFinite(value) ? value : low;
|
|
96
|
+
const over = Boolean(options.over) || raw > high;
|
|
97
|
+
const now = Math.min(high, Math.max(low, raw));
|
|
98
|
+
const fraction = over ? 1 : (now - low) / (high - low);
|
|
99
|
+
const write = (n: number) => formatFigure(n, { ...options, signed: false });
|
|
100
|
+
const params = { value: write(raw), max: write(high), over: write(Math.max(0, raw - high)) };
|
|
101
|
+
const text = over && raw > high
|
|
102
|
+
? translate("{value} of {max}, over by {over}", params)
|
|
103
|
+
: translate("{value} of {max}", params);
|
|
104
|
+
return { now, min: low, max: high, text, fraction, over };
|
|
105
|
+
}
|