@dialpad/dialtone-vue 4.5.0 → 4.6.1
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/{RichTextEditor-DaOHmXD_.js → RichTextEditor-D8DfONFm.js} +7 -7
- package/dist/{RichTextEditor-DaOHmXD_.js.map → RichTextEditor-D8DfONFm.js.map} +1 -1
- package/dist/{RichTextEditor-7eY8gy9u.cjs → RichTextEditor-DMUDJKVn.cjs} +2 -2
- package/dist/{RichTextEditor-7eY8gy9u.cjs.map → RichTextEditor-DMUDJKVn.cjs.map} +1 -1
- package/dist/common/sr_only_close_button.vue.d.ts +18 -1
- package/dist/component-documentation.json +1 -1
- package/dist/components/Avatar/Avatar.vue.d.ts +12 -8
- package/dist/components/Avatar/Avatar.vue.d.ts.map +1 -1
- package/dist/components/Badge/Badge.vue.d.ts +1 -2
- package/dist/components/Banner/Banner.vue.d.ts +36 -2
- package/dist/components/Banner/Banner.vue.d.ts.map +1 -1
- package/dist/components/Button/Button.vue.d.ts +18 -1
- package/dist/components/Button/Button.vue.d.ts.map +1 -1
- package/dist/components/Chip/Chip.vue.d.ts +18 -1
- package/dist/components/Chip/Chip.vue.d.ts.map +1 -1
- package/dist/components/Collapsible/Collapsible.vue.d.ts +18 -1
- package/dist/components/Collapsible/Collapsible.vue.d.ts.map +1 -1
- package/dist/components/ComboboxWithPopover/ComboboxWithPopover.vue.d.ts +36 -2
- package/dist/components/ComboboxWithPopover/ComboboxWithPopover.vue.d.ts.map +1 -1
- package/dist/components/Dropdown/Dropdown.vue.d.ts +36 -2
- package/dist/components/Dropdown/Dropdown.vue.d.ts.map +1 -1
- package/dist/components/FilterPill/FilterPill.vue.d.ts +90 -5
- package/dist/components/FilterPill/FilterPill.vue.d.ts.map +1 -1
- package/dist/components/Hovercard/Hovercard.vue.d.ts +72 -4
- package/dist/components/Hovercard/Hovercard.vue.d.ts.map +1 -1
- package/dist/components/ImageViewer/ImageViewer.vue.d.ts +36 -2
- package/dist/components/ImageViewer/ImageViewer.vue.d.ts.map +1 -1
- package/dist/components/Loader/Loader.vue.d.ts +18 -1
- package/dist/components/Loader/Loader.vue.d.ts.map +1 -1
- package/dist/components/Loader/LoaderConstants.d.ts +5 -0
- package/dist/components/Loader/LoaderConstants.d.ts.map +1 -0
- package/dist/components/Loader/index.d.ts +1 -0
- package/dist/components/Modal/Modal.vue.d.ts +37 -3
- package/dist/components/Modal/Modal.vue.d.ts.map +1 -1
- package/dist/components/Notice/Notice.vue.d.ts +36 -2
- package/dist/components/Notice/Notice.vue.d.ts.map +1 -1
- package/dist/components/Notice/NoticeAction.vue.d.ts +36 -2
- package/dist/components/Notice/NoticeAction.vue.d.ts.map +1 -1
- package/dist/components/Pagination/Pagination.vue.d.ts +18 -1
- package/dist/components/Pagination/Pagination.vue.d.ts.map +1 -1
- package/dist/components/Popover/Popover.vue.d.ts +36 -2
- package/dist/components/Popover/Popover.vue.d.ts.map +1 -1
- package/dist/components/Popover/PopoverHeaderFooter.vue.d.ts +18 -1
- package/dist/components/Popover/PopoverHeaderFooter.vue.d.ts.map +1 -1
- package/dist/components/RichTextEditor/Extensions/Mentions/MentionSuggestion.vue.d.ts +12 -8
- package/dist/components/RichTextEditor/Extensions/Variable/VariableComponent.vue.d.ts +55 -5
- package/dist/components/RichTextEditor/Extensions/Variable/VariableComponent.vue.d.ts.map +1 -1
- package/dist/components/SegmentedControl/SegmentedControlItem.vue.d.ts.map +1 -1
- package/dist/components/SplitButton/SplitButton.vue.d.ts +72 -4
- package/dist/components/SplitButton/SplitButton.vue.d.ts.map +1 -1
- package/dist/components/SplitButton/SplitButtonEnd.vue.d.ts +18 -1
- package/dist/components/SplitButton/SplitButtonEnd.vue.d.ts.map +1 -1
- package/dist/components/SplitButton/SplitButtonStart.vue.d.ts +18 -1
- package/dist/components/Tab/Tab.vue.d.ts +18 -1
- package/dist/components/Toast/Layouts/ToastLayoutAlternate.vue.d.ts +36 -2
- package/dist/components/Toast/Layouts/ToastLayoutAlternate.vue.d.ts.map +1 -1
- package/dist/components/Toast/Layouts/ToastLayoutDefault.vue.d.ts +36 -2
- package/dist/components/Toast/Layouts/ToastLayoutDefault.vue.d.ts.map +1 -1
- package/dist/components/Toast/Toast.vue.d.ts +144 -8
- package/dist/components/Toast/Toast.vue.d.ts.map +1 -1
- package/dist/dialtone-vue.cjs +1 -1
- package/dist/dialtone-vue.js +116 -115
- package/dist/lib/avatar/avatar.cjs +1 -1
- package/dist/lib/avatar/avatar.cjs.map +1 -1
- package/dist/lib/avatar/avatar.js +50 -47
- package/dist/lib/avatar/avatar.js.map +1 -1
- package/dist/lib/badge/badge.cjs +1 -1
- package/dist/lib/badge/badge.cjs.map +1 -1
- package/dist/lib/badge/badge.js +12 -14
- package/dist/lib/badge/badge.js.map +1 -1
- package/dist/lib/button/button.cjs +1 -1
- package/dist/lib/button/button.js +21 -21
- package/dist/lib/dropdown/dropdown.cjs.map +1 -1
- package/dist/lib/dropdown/dropdown.js.map +1 -1
- package/dist/lib/filter-pill/filter-pill.cjs +1 -1
- package/dist/lib/filter-pill/filter-pill.js +5 -5
- package/dist/lib/loader/index.cjs +1 -1
- package/dist/lib/loader/index.js +3 -2
- package/dist/lib/loader/loader-constants.cjs +2 -0
- package/dist/lib/loader/loader-constants.cjs.map +1 -0
- package/dist/lib/loader/loader-constants.js +9 -0
- package/dist/lib/loader/loader-constants.js.map +1 -0
- package/dist/lib/loader/loader.cjs +21 -21
- package/dist/lib/loader/loader.cjs.map +1 -1
- package/dist/lib/loader/loader.js +77 -14
- package/dist/lib/loader/loader.js.map +1 -1
- package/dist/lib/modal/modal.cjs +1 -1
- package/dist/lib/modal/modal.cjs.map +1 -1
- package/dist/lib/modal/modal.js +6 -5
- package/dist/lib/modal/modal.js.map +1 -1
- package/dist/lib/rich-text-editor/index.cjs +1 -1
- package/dist/lib/rich-text-editor/index.js +1 -1
- package/dist/lib/rich-text-editor/rich-text-editor.cjs +1 -1
- package/dist/lib/rich-text-editor/rich-text-editor.js +1 -1
- package/dist/lib/segmented-control/segmented-control-item.cjs.map +1 -1
- package/dist/lib/segmented-control/segmented-control-item.js.map +1 -1
- package/dist/lib/text/text.cjs.map +1 -1
- package/dist/lib/text/text.js.map +1 -1
- package/dist/localization/index.cjs +1 -1
- package/dist/localization/index.cjs.map +1 -1
- package/dist/localization/index.js +50 -33
- package/dist/localization/index.js.map +1 -1
- package/package.json +5 -5
package/dist/lib/modal/modal.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}}),require(`../../chunk-Bmb41Sf3.cjs`);const e=require(`../../common/constants/index.cjs`),t=require(`../../common/utils/index.cjs`),n=require(`../../_plugin-vue_export-helper-D8jCH6HB.cjs`),r=require(`../../common/mixins/mode.cjs`),i=require(`../notice/notice-constants.cjs`),a=require(`../text/text.cjs`),o=require(`../../localization/index.cjs`),s=require(`../button/button.cjs`),c=require(`../../shared/sr_only_close_button.cjs`),l=require(`./modal-constants.cjs`);let u=require(`vue`),d=require(`@dialpad/dialtone-icons/vue`);var f=`button:not(:disabled),[href],input:not(:disabled),select:not(:disabled),textarea:not(:disabled),details,[tabindex]:not([tabindex="-1"]):not(:disabled):not([aria-disabled="true"])`,p={name:`DtModal`,components:{DtButton:s.default,DtText:a.default,DtIconClose:d.DtIconClose,SrOnlyCloseButton:c.default},mixins:[r.default],props:{copy:{type:String,default:``},describedById:{type:String,default:``},labelledById:{type:String,default:function(){return t.getUniqueString()}},open:{type:Boolean,default:!1},headerText:{type:String,default:void 0},bannerHeaderText:{type:String,default:void 0},kind:{type:String,default:`default`,validator:e=>Object.keys(l.MODAL_KIND_MODIFIERS).includes(e)},fullscreen:{type:Boolean,default:!1},modalClass:{type:[String,Object,Array],default:``},dialogClass:{type:[String,Object,Array],default:``},contentClass:{type:[String,Object,Array],default:``},bannerKind:{type:String,default:`warning`,validator(e){return i.NOTICE_KINDS.includes(e)}},bannerClass:{type:[String,Object,Array],default:``},headerClass:{type:[String,Object,Array],default:``},footerClass:{type:[String,Object,Array],default:``},showClose:{type:Boolean,default:!0},closeOnClick:{type:Boolean,default:!0},fixedHeaderFooter:{type:Boolean,default:!0},initialFocusElement:{type:[String,e.HTML_ELEMENT_TYPE],default:`first`,validator:e=>e===`first`||e instanceof HTMLElement||e.startsWith(`#`)},appendTo:{type:String,default:void 0},transparentBackdrop:{type:Boolean,default:!1},modal:{type:Boolean,default:!1}},emits:[`click`,`keydown`,`update:open`],data(){return{MODAL_KIND_MODIFIERS:l.MODAL_KIND_MODIFIERS,MODAL_BANNER_KINDS:l.MODAL_BANNER_KINDS,hasSlotContent:t.hasSlotContent,i18n:new o.DialtoneLocalization,autoTeleportTarget:null,mousedownOnBackdrop:!1,mouseupOnBackdrop:!1}},computed:{
|
|
1
|
+
Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}}),require(`../../chunk-Bmb41Sf3.cjs`);const e=require(`../../common/constants/index.cjs`),t=require(`../../common/utils/index.cjs`),n=require(`../../_plugin-vue_export-helper-D8jCH6HB.cjs`),r=require(`../../common/mixins/mode.cjs`),i=require(`../notice/notice-constants.cjs`),a=require(`../text/text.cjs`),o=require(`../../localization/index.cjs`),s=require(`../button/button.cjs`),c=require(`../../shared/sr_only_close_button.cjs`),l=require(`./modal-constants.cjs`);let u=require(`vue`),d=require(`@dialpad/dialtone-icons/vue`);var f=`button:not(:disabled),[href],input:not(:disabled),select:not(:disabled),textarea:not(:disabled),details,[tabindex]:not([tabindex="-1"]):not(:disabled):not([aria-disabled="true"])`,p={name:`DtModal`,components:{DtButton:s.default,DtText:a.default,DtIconClose:d.DtIconClose,SrOnlyCloseButton:c.default},mixins:[r.default],props:{copy:{type:String,default:``},describedById:{type:String,default:``},labelledById:{type:String,default:function(){return t.getUniqueString()}},open:{type:Boolean,default:!1},headerText:{type:String,default:void 0},bannerHeaderText:{type:String,default:void 0},kind:{type:String,default:`default`,validator:e=>Object.keys(l.MODAL_KIND_MODIFIERS).includes(e)},fullscreen:{type:Boolean,default:!1},modalClass:{type:[String,Object,Array],default:``},dialogClass:{type:[String,Object,Array],default:``},contentClass:{type:[String,Object,Array],default:``},bannerKind:{type:String,default:`warning`,validator(e){return i.NOTICE_KINDS.includes(e)}},bannerClass:{type:[String,Object,Array],default:``},headerClass:{type:[String,Object,Array],default:``},footerClass:{type:[String,Object,Array],default:``},showClose:{type:Boolean,default:!0},closeOnClick:{type:Boolean,default:!0},fixedHeaderFooter:{type:Boolean,default:!0},initialFocusElement:{type:[String,e.HTML_ELEMENT_TYPE],default:`first`,validator:e=>e===`first`||e instanceof HTMLElement||e.startsWith(`#`)},appendTo:{type:String,default:void 0},transparentBackdrop:{type:Boolean,default:!1},modal:{type:Boolean,default:!1}},emits:[`click`,`keydown`,`update:open`],data(){return{MODAL_KIND_MODIFIERS:l.MODAL_KIND_MODIFIERS,MODAL_BANNER_KINDS:l.MODAL_BANNER_KINDS,hasSlotContent:t.hasSlotContent,i18n:new o.DialtoneLocalization,autoTeleportTarget:null,mousedownOnBackdrop:!1,mouseupOnBackdrop:!1}},computed:{bannerKindClass(){return l.MODAL_BANNER_KINDS[this.bannerKind]},closeButtonTitle(){return this.i18n.$t(`DIALTONE_CLOSE_BUTTON`)}},watch:{open(e){this.syncDialogState(e)}},mounted(){if(!this.appendTo){let e=this.$el?.getRootNode();if(e instanceof ShadowRoot){this.autoTeleportTarget=e,this.open&&this.$nextTick(()=>{this.open&&this.syncDialogState(!0)});return}}this.open&&this.syncDialogState(!0)},beforeUnmount(){let e=this.$refs.dialogEl;e?.open&&(e.close(),t.enableRootScrolling(this.getScrollRoot())),this.previousActiveElement=null},methods:{hasFooterSlot(){return!!this.$slots.footer},getScrollRoot(){return t.returnFirstEl(this.$refs.dialogEl)?.getRootNode()?.host},syncDialogState(e){let n=this.$refs.dialogEl;n&&(e?(this.previousActiveElement=document.activeElement,n.open||(this.modal?n.showModal():n.show()),t.disableRootScrolling(this.getScrollRoot())):n.open&&t.enableRootScrolling(this.getScrollRoot()))},close(){this.$emit(`update:open`,!1)},onBackdropMousedown(e){this.mousedownOnBackdrop=e.target===e.currentTarget},onBackdropMouseup(e){this.mouseupOnBackdrop=e.target===e.currentTarget},onBackdropClick(e){let t=this.mousedownOnBackdrop&&this.mouseupOnBackdrop;this.closeOnClick&&e.target===e.currentTarget&&t&&this.close(),this.$emit(`click`,e)},onKeydown(e){!this.modal&&e.key===`Escape`&&!e.defaultPrevented&&(e.preventDefault(),this.close()),this.$emit(`keydown`,e)},async onAfterEnter(){this.$emit(`update:open`,!0),await this.setFocusAfterTransition()},onAfterLeave(){let e=this.$refs.dialogEl;e?.open&&e.close(),this.previousActiveElement?.focus(),this.previousActiveElement=null},focusFirstTabbable(e){let t=[...e.querySelectorAll(f)];if(!t.length)return;let n=t[0];n.matches(`[type="radio"]:not(:checked)`)&&(n=t.find(e=>e.checked&&e.name===n.name)||n),n.focus({preventScroll:!0})},async setFocusAfterTransition(){let e=this.$refs.dialogEl;if(e)if(await this.$nextTick(),this.initialFocusElement===`first`)this.focusFirstTabbable(e);else if(typeof this.initialFocusElement==`string`&&this.initialFocusElement.startsWith(`#`)){let t=e.querySelector(this.initialFocusElement);t?t.focus():(console.warn(`Could not find the element specified in dt-modal prop "initialFocusElement". Defaulting to focusing the first element.`),this.focusFirstTabbable(e))}else this.initialFocusElement instanceof HTMLElement&&this.initialFocusElement.focus()}}},m=[`aria-modal`,`aria-describedby`,`aria-labelledby`],h=[`id`];function g(e,t,n,r,i,a){let o=(0,u.resolveComponent)(`dt-text`),s=(0,u.resolveComponent)(`sr-only-close-button`),c=(0,u.resolveComponent)(`dt-icon-close`),l=(0,u.resolveComponent)(`dt-button`),d=(0,u.resolveDirective)(`dt-focustrap`);return(0,u.openBlock)(),(0,u.createBlock)(u.Teleport,{disabled:!n.appendTo&&!i.autoTeleportTarget,to:n.appendTo||i.autoTeleportTarget},[(0,u.withDirectives)(((0,u.openBlock)(),(0,u.createElementBlock)(`dialog`,(0,u.mergeProps)({ref:`dialogEl`,class:[`d-modal`,i.MODAL_KIND_MODIFIERS[n.kind],{"d-modal--full":n.fullscreen},{"d-modal--transparent-backdrop":n.transparentBackdrop},n.modalClass],"data-qa":`dt-modal`,"aria-modal":n.modal?`true`:void 0,"aria-describedby":n.describedById||void 0,"aria-labelledby":n.labelledById},e.modeAttrs,{onCancel:t[0]||(t[0]=(0,u.withModifiers)((...e)=>a.close&&a.close(...e),[`prevent`])),onMousedown:t[1]||(t[1]=(...e)=>a.onBackdropMousedown&&a.onBackdropMousedown(...e)),onMouseup:t[2]||(t[2]=(...e)=>a.onBackdropMouseup&&a.onBackdropMouseup(...e)),onClick:t[3]||(t[3]=(...e)=>a.onBackdropClick&&a.onBackdropClick(...e)),onKeydown:t[4]||(t[4]=(...e)=>a.onKeydown&&a.onKeydown(...e))}),[n.open&&(i.hasSlotContent(e.$slots.banner)||n.bannerHeaderText)?((0,u.openBlock)(),(0,u.createElementBlock)(`div`,{key:0,"data-qa":`dt-modal-banner`,class:(0,u.normalizeClass)([`d-modal__banner`,n.bannerClass,a.bannerKindClass])},[(0,u.renderSlot)(e.$slots,`banner`,{},()=>[(0,u.createTextVNode)((0,u.toDisplayString)(n.bannerHeaderText),1)])],2)):(0,u.createCommentVNode)(``,!0),(0,u.createVNode)(u.Transition,{appear:n.open,name:`d-modal__dialog`,onAfterEnter:a.onAfterEnter,onAfterLeave:a.onAfterLeave},{default:(0,u.withCtx)(()=>[(0,u.withDirectives)((0,u.createElementVNode)(`div`,{class:(0,u.normalizeClass)([`d-modal__dialog`,{"d-modal__dialog--scrollable":n.fixedHeaderFooter},n.dialogClass])},[i.hasSlotContent(e.$slots.header)?((0,u.openBlock)(),(0,u.createElementBlock)(`div`,{key:0,id:n.labelledById,class:(0,u.normalizeClass)([`d-modal__header`,n.headerClass]),"data-qa":`dt-modal-title`},[(0,u.renderSlot)(e.$slots,`header`)],10,h)):((0,u.openBlock)(),(0,u.createBlock)(o,{key:1,id:n.labelledById,kind:`headline`,size:600,strength:`medium`,density:`100`,"text-box-trim":`start`,as:`h2`,class:(0,u.normalizeClass)([`d-modal__header`,n.headerClass]),"data-qa":`dt-modal-title`},{default:(0,u.withCtx)(()=>[(0,u.createTextVNode)((0,u.toDisplayString)(n.headerText),1)]),_:1},8,[`id`,`class`])),i.hasSlotContent(e.$slots.default)?((0,u.openBlock)(),(0,u.createElementBlock)(`div`,{key:2,class:(0,u.normalizeClass)([`d-modal__content`,n.contentClass]),"data-qa":`dt-modal-copy`},[(0,u.renderSlot)(e.$slots,`default`)],2)):((0,u.openBlock)(),(0,u.createElementBlock)(`p`,{key:3,class:(0,u.normalizeClass)([`d-modal__content`,n.contentClass]),"data-qa":`dt-modal-copy`},(0,u.toDisplayString)(n.copy),3)),a.hasFooterSlot()?((0,u.openBlock)(),(0,u.createElementBlock)(`footer`,{key:4,class:(0,u.normalizeClass)([`d-modal__footer`,n.footerClass]),"data-qa":`dt-modal-footer`},[(0,u.renderSlot)(e.$slots,`footer`)],2)):(0,u.createCommentVNode)(``,!0),n.showClose?((0,u.openBlock)(),(0,u.createBlock)(l,{key:6,class:`d-modal__close`,"data-qa":`dt-modal-close-button`,size:300,kind:`muted`,importance:`clear`,"aria-label":a.closeButtonTitle,title:a.closeButtonTitle,onClick:a.close},{icon:(0,u.withCtx)(({iconSize:e})=>[(0,u.createVNode)(c,{size:e},null,8,[`size`])]),_:1},8,[`aria-label`,`title`,`onClick`])):((0,u.openBlock)(),(0,u.createBlock)(s,{key:5,onClose:a.close},null,8,[`onClose`]))],2),[[u.vShow,n.open]])]),_:3},8,[`appear`,`onAfterEnter`,`onAfterLeave`])],16,m)),[[d,{active:n.open,initialFocus:!1,restoreFocus:!1}]])],8,[`disabled`,`to`])}var _=n.t(p,[[`render`,g]]);exports.default=_;
|
|
2
2
|
//# sourceMappingURL=modal.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"modal.cjs","names":[],"sources":["../../../components/Modal/Modal.vue"],"sourcesContent":["<template>\n <teleport\n :disabled=\"!appendTo && !autoTeleportTarget\"\n :to=\"appendTo || autoTeleportTarget\"\n >\n <!-- eslint-disable-next-line vuejs-accessibility/no-static-element-interactions -->\n <dialog\n ref=\"dialogEl\"\n v-dt-focustrap=\"{ active: open, initialFocus: false, restoreFocus: false }\"\n :class=\"[\n 'd-modal',\n MODAL_KIND_MODIFIERS[kind],\n { 'd-modal--full': fullscreen },\n { 'd-modal--transparent-backdrop': transparentBackdrop },\n modalClass,\n ]\"\n data-qa=\"dt-modal\"\n :aria-modal=\"modal ? 'true' : undefined\"\n :aria-describedby=\"describedById || undefined\"\n :aria-labelledby=\"labelledById\"\n v-bind=\"modeAttrs\"\n @cancel.prevent=\"close\"\n @mousedown=\"onBackdropMousedown\"\n @mouseup=\"onBackdropMouseup\"\n @click=\"onBackdropClick\"\n @keydown=\"onKeydown\"\n >\n <div\n v-if=\"open && (hasSlotContent($slots.banner) || bannerHeaderText)\"\n data-qa=\"dt-modal-banner\"\n :class=\"[\n 'd-modal__banner',\n bannerClass,\n bannerKindClass,\n ]\"\n >\n <!-- @slot Slot for the banner, defaults to bannerHeaderText prop -->\n <slot name=\"banner\">\n {{ bannerHeaderText }}\n </slot>\n </div>\n <transition\n :appear=\"open\"\n name=\"d-modal__dialog\"\n @after-enter=\"onAfterEnter\"\n @after-leave=\"onAfterLeave\"\n >\n <div\n v-show=\"open\"\n :class=\"[\n 'd-modal__dialog',\n { 'd-modal__dialog--scrollable': fixedHeaderFooter },\n dialogClass,\n ]\"\n >\n <div\n v-if=\"hasSlotContent($slots.header)\"\n :id=\"labelledById\"\n :class=\"['d-modal__header', headerClass]\"\n data-qa=\"dt-modal-title\"\n >\n <!-- @slot Slot for dialog header section, taking the place of any \"headerText\" text prop -->\n <slot name=\"header\" />\n </div>\n <dt-text\n v-else\n :id=\"labelledById\"\n kind=\"headline\"\n :size=\"600\"\n strength=\"medium\"\n density=\"100\"\n text-box-trim=\"start\"\n as=\"h2\"\n :class=\"['d-modal__header', headerClass]\"\n data-qa=\"dt-modal-title\"\n >\n {{ headerText }}\n </dt-text>\n <div\n v-if=\"hasSlotContent($slots.default)\"\n :class=\"[\n 'd-modal__content',\n contentClass,\n ]\"\n data-qa=\"dt-modal-copy\"\n >\n <!-- @slot Default slot for dialog body section, taking the place of any \"copy\" text prop -->\n <slot />\n </div>\n <p\n v-else\n :class=\"[\n 'd-modal__content',\n contentClass,\n ]\"\n data-qa=\"dt-modal-copy\"\n >\n {{ copy }}\n </p>\n <footer\n v-if=\"hasFooterSlot\"\n :class=\"['d-modal__footer', footerClass]\"\n >\n <!-- @slot Slot for dialog footer content, often containing cancel and confirm buttons. -->\n <slot name=\"footer\" />\n </footer>\n <sr-only-close-button\n v-if=\"!showClose\"\n @close=\"close\"\n />\n <dt-button\n v-else\n class=\"d-modal__close\"\n data-qa=\"dt-modal-close-button\"\n :size=\"300\"\n kind=\"muted\"\n importance=\"clear\"\n :aria-label=\"closeButtonTitle\"\n :title=\"closeButtonTitle\"\n @click=\"close\"\n >\n <template #icon=\"{ iconSize }\">\n <dt-icon-close\n :size=\"iconSize\"\n />\n </template>\n </dt-button>\n </div>\n </transition>\n </dialog>\n </teleport>\n</template>\n\n<script>\n/* eslint-disable max-lines */\nimport { DtButton } from '@/components/Button';\nimport { DtText } from '@/components/Text';\nimport { DtIconClose } from '@dialpad/dialtone-icons/vue';\nimport ModeMixin from '@/common/mixins/mode';\nimport {\n MODAL_BANNER_KINDS,\n MODAL_KIND_MODIFIERS,\n} from './ModalConstants';\nimport { getUniqueString, hasSlotContent, returnFirstEl, disableRootScrolling, enableRootScrolling } from '@/common/utils';\nimport { HTML_ELEMENT_TYPE } from '@/common/constants';\nimport SrOnlyCloseButton from '@/common/sr_only_close_button.vue';\nimport { NOTICE_KINDS } from '@/components/Notice';\nimport { DialtoneLocalization } from '@/localization';\n\nconst focusableSelector = 'button:not(:disabled),[href],input:not(:disabled),select:not(:disabled),' +\n 'textarea:not(:disabled),details,[tabindex]:not([tabindex=\"-1\"]):not(:disabled):not([aria-disabled=\"true\"])';\n\n/**\n * Modals focus the user's attention exclusively on one task or piece of information\n * via a window that sits on top of the page content.\n * @see https://dialtone.dialpad.com/components/modal.html\n */\nexport default {\n name: 'DtModal',\n\n components: {\n DtButton,\n DtText,\n DtIconClose,\n SrOnlyCloseButton,\n },\n\n mixins: [ModeMixin],\n\n props: {\n /**\n * Body text to display as the modal's main content.\n */\n copy: {\n type: String,\n default: '',\n },\n\n /**\n * Id to use for the dialog's aria-describedby.\n * Recommended only if the dialog content itself isn't enough to give full context,\n * as screen readers should recite the dialog contents by default before any aria-description.\n */\n describedById: {\n type: String,\n default: '',\n },\n\n /**\n * Id to use for the dialog's aria-labelledby.\n */\n labelledById: {\n type: String,\n default: function () { return getUniqueString(); },\n },\n\n /**\n * Whether the modal should be shown.\n * Parent component can sync on this value to control the modal's visibility.\n * @values true, false\n */\n open: {\n type: Boolean,\n default: false,\n },\n\n /**\n * Header text to display in the modal header.\n */\n headerText: {\n type: String,\n default: undefined,\n },\n\n /**\n * Header text to display in the modal banner.\n */\n bannerHeaderText: {\n type: String,\n default: undefined,\n },\n\n /**\n * The theme of the modal.\n * @values default, critical\n */\n kind: {\n type: String,\n default: 'default',\n validator: (k) => Object.keys(MODAL_KIND_MODIFIERS).includes(k),\n },\n\n /**\n * Whether the modal fills the viewport instead of rendering at its default size.\n * @values true, false\n */\n fullscreen: {\n type: Boolean,\n default: false,\n },\n\n /**\n * Additional class name for the root modal element.\n * Can accept String, Object, and Array, i.e. has the\n * same API as Vue's built-in handling of the class attribute.\n */\n modalClass: {\n type: [String, Object, Array],\n default: '',\n },\n\n /**\n * Additional class name for the dialog element within the modal.\n * Can accept String, Object, and Array, i.e. has the\n * same API as Vue's built-in handling of the class attribute.\n */\n dialogClass: {\n type: [String, Object, Array],\n default: '',\n },\n\n /**\n * Additional class name for the content element within the modal.\n * Can accept String, Object, and Array, i.e. has the\n * same API as Vue's built-in handling of the class attribute.\n */\n contentClass: {\n type: [String, Object, Array],\n default: '',\n },\n\n /**\n * Sets the color of the banner.\n * @values base, critical, info, positive, warning\n */\n bannerKind: {\n type: String,\n default: 'warning',\n validator (kind) {\n return NOTICE_KINDS.includes(kind);\n },\n },\n\n /**\n * Additional class name for the banner element within the modal.\n * Can accept String, Object, and Array, i.e. has the\n * same API as Vue's built-in handling of the class attribute.\n */\n bannerClass: {\n type: [String, Object, Array],\n default: '',\n },\n\n /**\n * Additional class name for the header element within the modal.\n * Can accept String, Object, and Array, i.e. has the\n * same API as Vue's built-in handling of the class attribute.\n */\n headerClass: {\n type: [String, Object, Array],\n default: '',\n },\n\n /**\n * Additional class name for the footer element within the modal.\n * Can accept String, Object, and Array, i.e. has the\n * same API as Vue's built-in handling of the class attribute.\n */\n footerClass: {\n type: [String, Object, Array],\n default: '',\n },\n\n /**\n * Shows the close button on the modal\n * @values true, false\n */\n showClose: {\n type: Boolean,\n default: true,\n },\n\n /**\n * Whether the modal will close when you click outside of the dialog on the overlay.\n * @values true, false\n */\n closeOnClick: {\n type: Boolean,\n default: true,\n },\n\n /**\n * Scrollable modal that allows scroll the modal content keeping the header and footer fixed\n * @values true, false\n */\n fixedHeaderFooter: {\n type: Boolean,\n default: true,\n },\n\n /**\n * The element that is focused when the modal is opened. This can be an\n * HTMLElement within the modal, a string starting with '#' which will\n * find the element by ID. 'first' which will automatically focus\n * the first element, or 'dialog' which will focus the dialog window itself.\n * If the dialog is modal this prop cannot be 'none'.\n */\n initialFocusElement: {\n type: [String, HTML_ELEMENT_TYPE],\n default: 'first',\n validator: initialFocusElement => {\n return initialFocusElement === 'first' ||\n (initialFocusElement instanceof HTMLElement) ||\n initialFocusElement.startsWith('#');\n },\n },\n\n /**\n * A CSS selector string for the element to portal the modal to. If not provided, the modal will be rendered in its default location.\n */\n appendTo: {\n type: String,\n default: undefined,\n },\n\n /**\n * When true, the surrounding backdrop is rendered fully transparent\n * instead of the default dimming overlay. The dialog box itself\n * remains opaque. Useful when the underlying UI should remain visible.\n * @values true, false\n */\n transparentBackdrop: {\n type: Boolean,\n default: false,\n },\n\n /**\n * When true, the dialog opens with showModal(), which promotes it to the browser\n * top layer. Nothing outside the top layer can paint above it regardless of\n * z-index, so application surfaces such as toasts and call notifications end up\n * behind it. When false, it opens with show() and stays in the normal stacking\n * order, where the Dialtone z-index scale applies and --zi-notification (700)\n * outranks --zi-modal (600) as documented.\n *\n * Focus trapping, scroll locking and Esc-to-close behave identically in both\n * modes. Background inertness does not: only the top layer provides it, so with\n * modal unset the page outside the dialog stays reachable. That is deliberate —\n * it is what lets an application's own overlays remain usable above a modal —\n * and keyboard containment still comes from the focus trap.\n * @values true, false\n */\n modal: {\n type: Boolean,\n default: false,\n },\n },\n\n emits: [\n /**\n * Native button click event\n *\n * @event click\n * @type {PointerEvent | KeyboardEvent}\n */\n 'click',\n\n /**\n * Native keydown event\n *\n * @event keydown\n * @type {KeyboardEvent}\n */\n 'keydown',\n\n /**\n * The modal will emit a \"false\" boolean value for this event when the user performs a modal-closing action.\n * Parent components can sync on this value to create a 2-way binding to control modal visibility.\n *\n * @event update:open\n * @type {Boolean}\n */\n 'update:open',\n ],\n\n data () {\n return {\n MODAL_KIND_MODIFIERS,\n MODAL_BANNER_KINDS,\n hasSlotContent,\n i18n: new DialtoneLocalization(),\n autoTeleportTarget: null,\n mousedownOnBackdrop: false,\n mouseupOnBackdrop: false,\n };\n },\n\n computed: {\n hasFooterSlot () {\n return !!this.$slots.footer;\n },\n\n bannerKindClass () {\n return MODAL_BANNER_KINDS[this.bannerKind];\n },\n\n closeButtonTitle () {\n return this.i18n.$t('DIALTONE_CLOSE_BUTTON');\n },\n },\n\n watch: {\n open (isShowing) {\n this.syncDialogState(isShowing);\n },\n },\n\n mounted () {\n if (!this.appendTo) {\n const root = this.$el?.getRootNode();\n if (root instanceof ShadowRoot) {\n this.autoTeleportTarget = root;\n // Defer syncDialogState so the teleport renders inside the shadow root first.\n if (this.open) this.$nextTick(() => { if (this.open) this.syncDialogState(true); });\n return;\n }\n }\n if (this.open) {\n this.syncDialogState(true);\n }\n },\n\n beforeUnmount () {\n const dialogEl = this.$refs.dialogEl;\n if (dialogEl?.open) {\n dialogEl.close();\n enableRootScrolling(this.getScrollRoot());\n }\n this.previousActiveElement = null;\n },\n\n methods: {\n getScrollRoot () {\n return returnFirstEl(this.$refs.dialogEl)?.getRootNode()?.host;\n },\n\n syncDialogState (isShowing) {\n const dialogEl = this.$refs.dialogEl;\n if (!dialogEl) return;\n\n if (isShowing) {\n this.previousActiveElement = document.activeElement;\n if (!dialogEl.open) {\n // show() leaves the dialog in the normal stacking order instead of the\n // top layer, where the z-index scale still applies.\n if (this.modal) dialogEl.showModal(); else dialogEl.show();\n }\n disableRootScrolling(this.getScrollRoot());\n } else if (dialogEl.open) {\n // Leave transition plays via v-show on inner content.\n // close() is called in onAfterLeave when transition completes.\n enableRootScrolling(this.getScrollRoot());\n }\n },\n\n\n\n close () {\n this.$emit('update:open', false);\n },\n\n onBackdropMousedown (event) {\n this.mousedownOnBackdrop = event.target === event.currentTarget;\n },\n\n onBackdropMouseup (event) {\n this.mouseupOnBackdrop = event.target === event.currentTarget;\n },\n\n onBackdropClick (event) {\n const pressedAndReleasedOnBackdrop = this.mousedownOnBackdrop && this.mouseupOnBackdrop;\n if (this.closeOnClick && event.target === event.currentTarget && pressedAndReleasedOnBackdrop) {\n this.close();\n }\n this.$emit('click', event);\n },\n\n onKeydown (event) {\n // The native cancel event only fires for dialogs opened with showModal(), so\n // Esc has to be handled explicitly to keep dismissal identical in both modes.\n // defaultPrevented means a nested widget (dropdown, combobox) already consumed\n // it to close itself, and the modal must not close out from under it.\n if (!this.modal && event.key === 'Escape' && !event.defaultPrevented) {\n event.preventDefault();\n this.close();\n }\n this.$emit('keydown', event);\n },\n\n async onAfterEnter () {\n this.$emit('update:open', true);\n await this.setFocusAfterTransition();\n },\n\n onAfterLeave () {\n const dialogEl = this.$refs.dialogEl;\n if (dialogEl?.open) {\n dialogEl.close();\n }\n this.previousActiveElement?.focus();\n this.previousActiveElement = null;\n },\n\n focusFirstTabbable (container) {\n const focusable = [...container.querySelectorAll(focusableSelector)];\n if (!focusable.length) return;\n let target = focusable[0];\n // If first focusable is an unchecked radio, prefer the checked radio in the same group.\n if (target.matches('[type=\"radio\"]:not(:checked)')) {\n target = focusable.find(el => el.checked && el.name === target.name) || target;\n }\n target.focus({ preventScroll: true });\n },\n\n async setFocusAfterTransition () {\n const dialogEl = this.$refs.dialogEl;\n if (!dialogEl) return;\n\n await this.$nextTick();\n\n if (this.initialFocusElement === 'first') {\n this.focusFirstTabbable(dialogEl);\n } else if (typeof this.initialFocusElement === 'string' && this.initialFocusElement.startsWith('#')) {\n const el = dialogEl.querySelector(this.initialFocusElement);\n if (el) {\n el.focus();\n } else {\n // eslint-disable-next-line no-console\n console.warn('Could not find the element specified in dt-modal prop \"initialFocusElement\". ' +\n 'Defaulting to focusing the first element.');\n this.focusFirstTabbable(dialogEl);\n }\n } else if (this.initialFocusElement instanceof HTMLElement) {\n this.initialFocusElement.focus();\n }\n },\n },\n};\n</script>\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"modal.cjs","names":[],"sources":["../../../components/Modal/Modal.vue"],"sourcesContent":["<template>\n <teleport\n :disabled=\"!appendTo && !autoTeleportTarget\"\n :to=\"appendTo || autoTeleportTarget\"\n >\n <!-- eslint-disable-next-line vuejs-accessibility/no-static-element-interactions -->\n <dialog\n ref=\"dialogEl\"\n v-dt-focustrap=\"{ active: open, initialFocus: false, restoreFocus: false }\"\n :class=\"[\n 'd-modal',\n MODAL_KIND_MODIFIERS[kind],\n { 'd-modal--full': fullscreen },\n { 'd-modal--transparent-backdrop': transparentBackdrop },\n modalClass,\n ]\"\n data-qa=\"dt-modal\"\n :aria-modal=\"modal ? 'true' : undefined\"\n :aria-describedby=\"describedById || undefined\"\n :aria-labelledby=\"labelledById\"\n v-bind=\"modeAttrs\"\n @cancel.prevent=\"close\"\n @mousedown=\"onBackdropMousedown\"\n @mouseup=\"onBackdropMouseup\"\n @click=\"onBackdropClick\"\n @keydown=\"onKeydown\"\n >\n <div\n v-if=\"open && (hasSlotContent($slots.banner) || bannerHeaderText)\"\n data-qa=\"dt-modal-banner\"\n :class=\"[\n 'd-modal__banner',\n bannerClass,\n bannerKindClass,\n ]\"\n >\n <!-- @slot Slot for the banner, defaults to bannerHeaderText prop -->\n <slot name=\"banner\">\n {{ bannerHeaderText }}\n </slot>\n </div>\n <transition\n :appear=\"open\"\n name=\"d-modal__dialog\"\n @after-enter=\"onAfterEnter\"\n @after-leave=\"onAfterLeave\"\n >\n <div\n v-show=\"open\"\n :class=\"[\n 'd-modal__dialog',\n { 'd-modal__dialog--scrollable': fixedHeaderFooter },\n dialogClass,\n ]\"\n >\n <div\n v-if=\"hasSlotContent($slots.header)\"\n :id=\"labelledById\"\n :class=\"['d-modal__header', headerClass]\"\n data-qa=\"dt-modal-title\"\n >\n <!-- @slot Slot for dialog header section, taking the place of any \"headerText\" text prop -->\n <slot name=\"header\" />\n </div>\n <dt-text\n v-else\n :id=\"labelledById\"\n kind=\"headline\"\n :size=\"600\"\n strength=\"medium\"\n density=\"100\"\n text-box-trim=\"start\"\n as=\"h2\"\n :class=\"['d-modal__header', headerClass]\"\n data-qa=\"dt-modal-title\"\n >\n {{ headerText }}\n </dt-text>\n <div\n v-if=\"hasSlotContent($slots.default)\"\n :class=\"[\n 'd-modal__content',\n contentClass,\n ]\"\n data-qa=\"dt-modal-copy\"\n >\n <!-- @slot Default slot for dialog body section, taking the place of any \"copy\" text prop -->\n <slot />\n </div>\n <p\n v-else\n :class=\"[\n 'd-modal__content',\n contentClass,\n ]\"\n data-qa=\"dt-modal-copy\"\n >\n {{ copy }}\n </p>\n <footer\n v-if=\"hasFooterSlot()\"\n :class=\"['d-modal__footer', footerClass]\"\n data-qa=\"dt-modal-footer\"\n >\n <!-- @slot Slot for dialog footer content, often containing cancel and confirm buttons. -->\n <slot name=\"footer\" />\n </footer>\n <sr-only-close-button\n v-if=\"!showClose\"\n @close=\"close\"\n />\n <dt-button\n v-else\n class=\"d-modal__close\"\n data-qa=\"dt-modal-close-button\"\n :size=\"300\"\n kind=\"muted\"\n importance=\"clear\"\n :aria-label=\"closeButtonTitle\"\n :title=\"closeButtonTitle\"\n @click=\"close\"\n >\n <template #icon=\"{ iconSize }\">\n <dt-icon-close\n :size=\"iconSize\"\n />\n </template>\n </dt-button>\n </div>\n </transition>\n </dialog>\n </teleport>\n</template>\n\n<script>\n/* eslint-disable max-lines */\nimport { DtButton } from '@/components/Button';\nimport { DtText } from '@/components/Text';\nimport { DtIconClose } from '@dialpad/dialtone-icons/vue';\nimport ModeMixin from '@/common/mixins/mode';\nimport {\n MODAL_BANNER_KINDS,\n MODAL_KIND_MODIFIERS,\n} from './ModalConstants';\nimport { getUniqueString, hasSlotContent, returnFirstEl, disableRootScrolling, enableRootScrolling } from '@/common/utils';\nimport { HTML_ELEMENT_TYPE } from '@/common/constants';\nimport SrOnlyCloseButton from '@/common/sr_only_close_button.vue';\nimport { NOTICE_KINDS } from '@/components/Notice';\nimport { DialtoneLocalization } from '@/localization';\n\nconst focusableSelector = 'button:not(:disabled),[href],input:not(:disabled),select:not(:disabled),' +\n 'textarea:not(:disabled),details,[tabindex]:not([tabindex=\"-1\"]):not(:disabled):not([aria-disabled=\"true\"])';\n\n/**\n * Modals focus the user's attention exclusively on one task or piece of information\n * via a window that sits on top of the page content.\n * @see https://dialtone.dialpad.com/components/modal.html\n */\nexport default {\n name: 'DtModal',\n\n components: {\n DtButton,\n DtText,\n DtIconClose,\n SrOnlyCloseButton,\n },\n\n mixins: [ModeMixin],\n\n props: {\n /**\n * Body text to display as the modal's main content.\n */\n copy: {\n type: String,\n default: '',\n },\n\n /**\n * Id to use for the dialog's aria-describedby.\n * Recommended only if the dialog content itself isn't enough to give full context,\n * as screen readers should recite the dialog contents by default before any aria-description.\n */\n describedById: {\n type: String,\n default: '',\n },\n\n /**\n * Id to use for the dialog's aria-labelledby.\n */\n labelledById: {\n type: String,\n default: function () { return getUniqueString(); },\n },\n\n /**\n * Whether the modal should be shown.\n * Parent component can sync on this value to control the modal's visibility.\n * @values true, false\n */\n open: {\n type: Boolean,\n default: false,\n },\n\n /**\n * Header text to display in the modal header.\n */\n headerText: {\n type: String,\n default: undefined,\n },\n\n /**\n * Header text to display in the modal banner.\n */\n bannerHeaderText: {\n type: String,\n default: undefined,\n },\n\n /**\n * The theme of the modal.\n * @values default, critical\n */\n kind: {\n type: String,\n default: 'default',\n validator: (k) => Object.keys(MODAL_KIND_MODIFIERS).includes(k),\n },\n\n /**\n * Whether the modal fills the viewport instead of rendering at its default size.\n * @values true, false\n */\n fullscreen: {\n type: Boolean,\n default: false,\n },\n\n /**\n * Additional class name for the root modal element.\n * Can accept String, Object, and Array, i.e. has the\n * same API as Vue's built-in handling of the class attribute.\n */\n modalClass: {\n type: [String, Object, Array],\n default: '',\n },\n\n /**\n * Additional class name for the dialog element within the modal.\n * Can accept String, Object, and Array, i.e. has the\n * same API as Vue's built-in handling of the class attribute.\n */\n dialogClass: {\n type: [String, Object, Array],\n default: '',\n },\n\n /**\n * Additional class name for the content element within the modal.\n * Can accept String, Object, and Array, i.e. has the\n * same API as Vue's built-in handling of the class attribute.\n */\n contentClass: {\n type: [String, Object, Array],\n default: '',\n },\n\n /**\n * Sets the color of the banner.\n * @values base, critical, info, positive, warning\n */\n bannerKind: {\n type: String,\n default: 'warning',\n validator (kind) {\n return NOTICE_KINDS.includes(kind);\n },\n },\n\n /**\n * Additional class name for the banner element within the modal.\n * Can accept String, Object, and Array, i.e. has the\n * same API as Vue's built-in handling of the class attribute.\n */\n bannerClass: {\n type: [String, Object, Array],\n default: '',\n },\n\n /**\n * Additional class name for the header element within the modal.\n * Can accept String, Object, and Array, i.e. has the\n * same API as Vue's built-in handling of the class attribute.\n */\n headerClass: {\n type: [String, Object, Array],\n default: '',\n },\n\n /**\n * Additional class name for the footer element within the modal.\n * Can accept String, Object, and Array, i.e. has the\n * same API as Vue's built-in handling of the class attribute.\n */\n footerClass: {\n type: [String, Object, Array],\n default: '',\n },\n\n /**\n * Shows the close button on the modal\n * @values true, false\n */\n showClose: {\n type: Boolean,\n default: true,\n },\n\n /**\n * Whether the modal will close when you click outside of the dialog on the overlay.\n * @values true, false\n */\n closeOnClick: {\n type: Boolean,\n default: true,\n },\n\n /**\n * Scrollable modal that allows scroll the modal content keeping the header and footer fixed\n * @values true, false\n */\n fixedHeaderFooter: {\n type: Boolean,\n default: true,\n },\n\n /**\n * The element that is focused when the modal is opened. This can be an\n * HTMLElement within the modal, a string starting with '#' which will\n * find the element by ID. 'first' which will automatically focus\n * the first element, or 'dialog' which will focus the dialog window itself.\n * If the dialog is modal this prop cannot be 'none'.\n */\n initialFocusElement: {\n type: [String, HTML_ELEMENT_TYPE],\n default: 'first',\n validator: initialFocusElement => {\n return initialFocusElement === 'first' ||\n (initialFocusElement instanceof HTMLElement) ||\n initialFocusElement.startsWith('#');\n },\n },\n\n /**\n * A CSS selector string for the element to portal the modal to. If not provided, the modal will be rendered in its default location.\n */\n appendTo: {\n type: String,\n default: undefined,\n },\n\n /**\n * When true, the surrounding backdrop is rendered fully transparent\n * instead of the default dimming overlay. The dialog box itself\n * remains opaque. Useful when the underlying UI should remain visible.\n * @values true, false\n */\n transparentBackdrop: {\n type: Boolean,\n default: false,\n },\n\n /**\n * When true, the dialog opens with showModal(), which promotes it to the browser\n * top layer. Nothing outside the top layer can paint above it regardless of\n * z-index, so application surfaces such as toasts and call notifications end up\n * behind it. When false, it opens with show() and stays in the normal stacking\n * order, where the Dialtone z-index scale applies and --zi-notification (700)\n * outranks --zi-modal (600) as documented.\n *\n * Focus trapping, scroll locking and Esc-to-close behave identically in both\n * modes. Background inertness does not: only the top layer provides it, so with\n * modal unset the page outside the dialog stays reachable. That is deliberate —\n * it is what lets an application's own overlays remain usable above a modal —\n * and keyboard containment still comes from the focus trap.\n * @values true, false\n */\n modal: {\n type: Boolean,\n default: false,\n },\n },\n\n emits: [\n /**\n * Native button click event\n *\n * @event click\n * @type {PointerEvent | KeyboardEvent}\n */\n 'click',\n\n /**\n * Native keydown event\n *\n * @event keydown\n * @type {KeyboardEvent}\n */\n 'keydown',\n\n /**\n * The modal will emit a \"false\" boolean value for this event when the user performs a modal-closing action.\n * Parent components can sync on this value to create a 2-way binding to control modal visibility.\n *\n * @event update:open\n * @type {Boolean}\n */\n 'update:open',\n ],\n\n data () {\n return {\n MODAL_KIND_MODIFIERS,\n MODAL_BANNER_KINDS,\n hasSlotContent,\n i18n: new DialtoneLocalization(),\n autoTeleportTarget: null,\n mousedownOnBackdrop: false,\n mouseupOnBackdrop: false,\n };\n },\n\n computed: {\n bannerKindClass () {\n return MODAL_BANNER_KINDS[this.bannerKind];\n },\n\n closeButtonTitle () {\n return this.i18n.$t('DIALTONE_CLOSE_BUTTON');\n },\n },\n\n watch: {\n open (isShowing) {\n this.syncDialogState(isShowing);\n },\n },\n\n mounted () {\n if (!this.appendTo) {\n const root = this.$el?.getRootNode();\n if (root instanceof ShadowRoot) {\n this.autoTeleportTarget = root;\n // Defer syncDialogState so the teleport renders inside the shadow root first.\n if (this.open) this.$nextTick(() => { if (this.open) this.syncDialogState(true); });\n return;\n }\n }\n if (this.open) {\n this.syncDialogState(true);\n }\n },\n\n beforeUnmount () {\n const dialogEl = this.$refs.dialogEl;\n if (dialogEl?.open) {\n dialogEl.close();\n enableRootScrolling(this.getScrollRoot());\n }\n this.previousActiveElement = null;\n },\n\n methods: {\n // Reads $slots, which is not reactive, so it must not be cached as a computed.\n hasFooterSlot () {\n return !!this.$slots.footer;\n },\n\n getScrollRoot () {\n return returnFirstEl(this.$refs.dialogEl)?.getRootNode()?.host;\n },\n\n syncDialogState (isShowing) {\n const dialogEl = this.$refs.dialogEl;\n if (!dialogEl) return;\n\n if (isShowing) {\n this.previousActiveElement = document.activeElement;\n if (!dialogEl.open) {\n // show() leaves the dialog in the normal stacking order instead of the\n // top layer, where the z-index scale still applies.\n if (this.modal) dialogEl.showModal(); else dialogEl.show();\n }\n disableRootScrolling(this.getScrollRoot());\n } else if (dialogEl.open) {\n // Leave transition plays via v-show on inner content.\n // close() is called in onAfterLeave when transition completes.\n enableRootScrolling(this.getScrollRoot());\n }\n },\n\n\n\n close () {\n this.$emit('update:open', false);\n },\n\n onBackdropMousedown (event) {\n this.mousedownOnBackdrop = event.target === event.currentTarget;\n },\n\n onBackdropMouseup (event) {\n this.mouseupOnBackdrop = event.target === event.currentTarget;\n },\n\n onBackdropClick (event) {\n const pressedAndReleasedOnBackdrop = this.mousedownOnBackdrop && this.mouseupOnBackdrop;\n if (this.closeOnClick && event.target === event.currentTarget && pressedAndReleasedOnBackdrop) {\n this.close();\n }\n this.$emit('click', event);\n },\n\n onKeydown (event) {\n // The native cancel event only fires for dialogs opened with showModal(), so\n // Esc has to be handled explicitly to keep dismissal identical in both modes.\n // defaultPrevented means a nested widget (dropdown, combobox) already consumed\n // it to close itself, and the modal must not close out from under it.\n if (!this.modal && event.key === 'Escape' && !event.defaultPrevented) {\n event.preventDefault();\n this.close();\n }\n this.$emit('keydown', event);\n },\n\n async onAfterEnter () {\n this.$emit('update:open', true);\n await this.setFocusAfterTransition();\n },\n\n onAfterLeave () {\n const dialogEl = this.$refs.dialogEl;\n if (dialogEl?.open) {\n dialogEl.close();\n }\n this.previousActiveElement?.focus();\n this.previousActiveElement = null;\n },\n\n focusFirstTabbable (container) {\n const focusable = [...container.querySelectorAll(focusableSelector)];\n if (!focusable.length) return;\n let target = focusable[0];\n // If first focusable is an unchecked radio, prefer the checked radio in the same group.\n if (target.matches('[type=\"radio\"]:not(:checked)')) {\n target = focusable.find(el => el.checked && el.name === target.name) || target;\n }\n target.focus({ preventScroll: true });\n },\n\n async setFocusAfterTransition () {\n const dialogEl = this.$refs.dialogEl;\n if (!dialogEl) return;\n\n await this.$nextTick();\n\n if (this.initialFocusElement === 'first') {\n this.focusFirstTabbable(dialogEl);\n } else if (typeof this.initialFocusElement === 'string' && this.initialFocusElement.startsWith('#')) {\n const el = dialogEl.querySelector(this.initialFocusElement);\n if (el) {\n el.focus();\n } else {\n // eslint-disable-next-line no-console\n console.warn('Could not find the element specified in dt-modal prop \"initialFocusElement\". ' +\n 'Defaulting to focusing the first element.');\n this.focusFirstTabbable(dialogEl);\n }\n } else if (this.initialFocusElement instanceof HTMLElement) {\n this.initialFocusElement.focus();\n }\n },\n },\n};\n</script>\n"],"mappings":"+mBAsJA,IAAM,EAAoB,qLAQrB,EAAU,CACb,KAAM,UAEN,WAAY,CACV,SAAA,EAAA,QACA,OAAA,EAAA,QACA,YAAA,EAAA,YACA,kBAAA,EAAA,QACD,CAED,OAAQ,CAAC,EAAA,QAAU,CAEnB,MAAO,CAIL,KAAM,CACJ,KAAM,OACN,QAAS,GACV,CAOD,cAAe,CACb,KAAM,OACN,QAAS,GACV,CAKD,aAAc,CACZ,KAAM,OACN,QAAS,UAAY,CAAE,OAAO,EAAA,iBAAiB,EAChD,CAOD,KAAM,CACJ,KAAM,QACN,QAAS,GACV,CAKD,WAAY,CACV,KAAM,OACN,QAAS,IAAA,GACV,CAKD,iBAAkB,CAChB,KAAM,OACN,QAAS,IAAA,GACV,CAMD,KAAM,CACJ,KAAM,OACN,QAAS,UACT,UAAY,GAAM,OAAO,KAAK,EAAA,qBAAqB,CAAC,SAAS,EAAE,CAChE,CAMD,WAAY,CACV,KAAM,QACN,QAAS,GACV,CAOD,WAAY,CACV,KAAM,CAAC,OAAQ,OAAQ,MAAM,CAC7B,QAAS,GACV,CAOD,YAAa,CACX,KAAM,CAAC,OAAQ,OAAQ,MAAM,CAC7B,QAAS,GACV,CAOD,aAAc,CACZ,KAAM,CAAC,OAAQ,OAAQ,MAAM,CAC7B,QAAS,GACV,CAMD,WAAY,CACV,KAAM,OACN,QAAS,UACT,UAAW,EAAM,CACf,OAAO,EAAA,aAAa,SAAS,EAAK,EAErC,CAOD,YAAa,CACX,KAAM,CAAC,OAAQ,OAAQ,MAAM,CAC7B,QAAS,GACV,CAOD,YAAa,CACX,KAAM,CAAC,OAAQ,OAAQ,MAAM,CAC7B,QAAS,GACV,CAOD,YAAa,CACX,KAAM,CAAC,OAAQ,OAAQ,MAAM,CAC7B,QAAS,GACV,CAMD,UAAW,CACT,KAAM,QACN,QAAS,GACV,CAMD,aAAc,CACZ,KAAM,QACN,QAAS,GACV,CAMD,kBAAmB,CACjB,KAAM,QACN,QAAS,GACV,CASD,oBAAqB,CACnB,KAAM,CAAC,OAAQ,EAAA,kBAAkB,CACjC,QAAS,QACT,UAAW,GACF,IAAwB,SAC5B,aAA+B,aAChC,EAAoB,WAAW,IAAI,CAExC,CAKD,SAAU,CACR,KAAM,OACN,QAAS,IAAA,GACV,CAQD,oBAAqB,CACnB,KAAM,QACN,QAAS,GACV,CAiBD,MAAO,CACL,KAAM,QACN,QAAS,GACV,CACF,CAED,MAAO,CAOL,QAQA,UASA,cACD,CAED,MAAQ,CACN,MAAO,CACL,qBAAA,EAAA,qBACA,mBAAA,EAAA,mBACA,eAAA,EAAA,eACA,KAAM,IAAI,EAAA,qBACV,mBAAoB,KACpB,oBAAqB,GACrB,kBAAmB,GACpB,EAGH,SAAU,CACR,iBAAmB,CACjB,OAAO,EAAA,mBAAmB,KAAK,aAGjC,kBAAoB,CAClB,OAAO,KAAK,KAAK,GAAG,wBAAwB,EAE/C,CAED,MAAO,CACL,KAAM,EAAW,CACf,KAAK,gBAAgB,EAAU,EAElC,CAED,SAAW,CACT,GAAI,CAAC,KAAK,SAAU,CAClB,IAAM,EAAO,KAAK,KAAK,aAAa,CACpC,GAAI,aAAgB,WAAY,CAC9B,KAAK,mBAAqB,EAEtB,KAAK,MAAM,KAAK,cAAgB,CAAM,KAAK,MAAM,KAAK,gBAAgB,GAAK,EAAI,CACnF,QAGA,KAAK,MACP,KAAK,gBAAgB,GAAK,EAI9B,eAAiB,CACf,IAAM,EAAW,KAAK,MAAM,SACxB,GAAU,OACZ,EAAS,OAAO,CAChB,EAAA,oBAAoB,KAAK,eAAe,CAAC,EAE3C,KAAK,sBAAwB,MAG/B,QAAS,CAEP,eAAiB,CACf,MAAO,CAAC,CAAC,KAAK,OAAO,QAGvB,eAAiB,CACf,OAAO,EAAA,cAAc,KAAK,MAAM,SAAS,EAAE,aAAa,EAAE,MAG5D,gBAAiB,EAAW,CAC1B,IAAM,EAAW,KAAK,MAAM,SACvB,IAED,GACF,KAAK,sBAAwB,SAAS,cACjC,EAAS,OAGR,KAAK,MAAO,EAAS,WAAW,CAAO,EAAS,MAAM,EAE5D,EAAA,qBAAqB,KAAK,eAAe,CAAC,EACjC,EAAS,MAGlB,EAAA,oBAAoB,KAAK,eAAe,CAAC,GAM7C,OAAS,CACP,KAAK,MAAM,cAAe,GAAM,EAGlC,oBAAqB,EAAO,CAC1B,KAAK,oBAAsB,EAAM,SAAW,EAAM,eAGpD,kBAAmB,EAAO,CACxB,KAAK,kBAAoB,EAAM,SAAW,EAAM,eAGlD,gBAAiB,EAAO,CACtB,IAAM,EAA+B,KAAK,qBAAuB,KAAK,kBAClE,KAAK,cAAgB,EAAM,SAAW,EAAM,eAAiB,GAC/D,KAAK,OAAO,CAEd,KAAK,MAAM,QAAS,EAAM,EAG5B,UAAW,EAAO,CAKZ,CAAC,KAAK,OAAS,EAAM,MAAQ,UAAY,CAAC,EAAM,mBAClD,EAAM,gBAAgB,CACtB,KAAK,OAAO,EAEd,KAAK,MAAM,UAAW,EAAM,EAG9B,MAAM,cAAgB,CACpB,KAAK,MAAM,cAAe,GAAK,CAC/B,MAAM,KAAK,yBAAyB,EAGtC,cAAgB,CACd,IAAM,EAAW,KAAK,MAAM,SACxB,GAAU,MACZ,EAAS,OAAO,CAElB,KAAK,uBAAuB,OAAO,CACnC,KAAK,sBAAwB,MAG/B,mBAAoB,EAAW,CAC7B,IAAM,EAAY,CAAC,GAAG,EAAU,iBAAiB,EAAkB,CAAC,CACpE,GAAI,CAAC,EAAU,OAAQ,OACvB,IAAI,EAAS,EAAU,GAEnB,EAAO,QAAQ,+BAA+B,GAChD,EAAS,EAAU,KAAK,GAAM,EAAG,SAAW,EAAG,OAAS,EAAO,KAAI,EAAK,GAE1E,EAAO,MAAM,CAAE,cAAe,GAAM,CAAC,EAGvC,MAAM,yBAA2B,CAC/B,IAAM,EAAW,KAAK,MAAM,SACvB,KAIL,GAFA,MAAM,KAAK,WAAW,CAElB,KAAK,sBAAwB,QAC/B,KAAK,mBAAmB,EAAS,SACxB,OAAO,KAAK,qBAAwB,UAAY,KAAK,oBAAoB,WAAW,IAAI,CAAE,CACnG,IAAM,EAAK,EAAS,cAAc,KAAK,oBAAoB,CACvD,EACF,EAAG,OAAO,EAGV,QAAQ,KAAK,yHACiC,CAC9C,KAAK,mBAAmB,EAAS,OAE1B,KAAK,+BAA+B,aAC7C,KAAK,oBAAoB,OAAO,EAGrC,CACF,oVAzcY,EAAA,SAAA,CAjIR,SAAQ,CAAG,EAAA,UAAQ,CAAK,EAAA,mBACxB,GAAI,EAAA,UAAY,EAAA,sFA+HR,UAAA,EAAA,EAAA,YAAA,CA3HP,IAAI,WAEH,MAAK,WAA+B,EAAA,qBAAqB,EAAA,uBAAkC,EAAA,WAAU,kCAA+C,EAAA,oBAAmB,CAAY,EAAA,YAOpL,UAAQ,WACP,aAAY,EAAA,MAAK,OAAY,IAAA,GAC7B,mBAAkB,EAAA,eAAiB,IAAA,GACnC,kBAAiB,EAAA,cACV,EAAA,UAAS,CAChB,SAAM,EAAA,KAAA,EAAA,IAAA,EAAA,EAAA,gBAAA,GAAA,IAAU,EAAA,OAAA,EAAA,MAAA,GAAA,EAAK,CAAA,CAAA,UAAA,CAAA,EACrB,YAAS,EAAA,KAAA,EAAA,IAAA,GAAA,IAAE,EAAA,qBAAA,EAAA,oBAAA,GAAA,EAAmB,EAC9B,UAAO,EAAA,KAAA,EAAA,IAAA,GAAA,IAAE,EAAA,mBAAA,EAAA,kBAAA,GAAA,EAAiB,EAC1B,QAAK,EAAA,KAAA,EAAA,IAAA,GAAA,IAAE,EAAA,iBAAA,EAAA,gBAAA,GAAA,EAAe,EACtB,UAAO,EAAA,KAAA,EAAA,IAAA,GAAA,IAAE,EAAA,WAAA,EAAA,UAAA,GAAA,EAAS,KAGX,EAAA,OAAS,EAAA,eAAe,EAAA,OAAO,OAAM,EAAK,EAAA,oBAAA,EAAA,EAAA,YAAA,EAAA,EAAA,EAAA,oBAY5C,MAAA,OAXJ,UAAQ,kBACP,OAAA,EAAA,EAAA,gBAAK,mBAA2C,EAAA,YAAuB,EAAA,qCASjE,EAAA,OAAA,SAAA,EAAA,KAAA,EAAA,EAAA,EAAA,kBAAA,EAAA,EAAA,iBADF,EAAA,iBAAgB,CAAA,EAAA,CAAA,CAAA,CAAA,CAAA,EAAA,GAAA,EAAA,EAAA,oBAAA,GAAA,GAAA,EAAA,EAAA,EAAA,aA2FV,EAAA,WAAA,CAvFV,OAAQ,EAAA,KACT,KAAK,kBACJ,aAAa,EAAA,aACb,aAAa,EAAA,yCAmFR,EAAA,EAAA,EAAA,iBAAA,EAAA,EAAA,oBAAA,MAAA,CA/EH,OAAA,EAAA,EAAA,gBAAK,kDAAgF,EAAA,kBAAiB,CAAgB,EAAA,gBAO/G,EAAA,eAAe,EAAA,OAAO,OAAM,GAAA,EAAA,EAAA,YAAA,EAAA,EAAA,EAAA,oBAO9B,MAAA,OANH,GAAI,EAAA,aACJ,OAAA,EAAA,EAAA,gBAAK,CAAA,kBAAsB,EAAA,YAAW,CAAA,CACvC,UAAQ,oCAGc,EAAA,OAAA,SAAA,CAAA,CAAA,GAAA,EAAA,IAAA,EAAA,EAAA,YAAA,EAAA,EAAA,EAAA,aAed,EAAA,OAXP,GAAI,EAAA,aACL,KAAK,WACJ,KAAM,IACP,SAAS,SACT,QAAQ,MACR,gBAAc,QACd,GAAG,KACF,OAAA,EAAA,EAAA,gBAAK,CAAA,kBAAsB,EAAA,YAAW,CAAA,CACvC,UAAQ,6CAEQ,EAAA,EAAA,EAAA,kBAAA,EAAA,EAAA,iBAAb,EAAA,WAAU,CAAA,EAAA,CAAA,CAAA,yBAGP,EAAA,eAAe,EAAA,OAAO,QAAO,GAAA,EAAA,EAAA,YAAA,EAAA,EAAA,EAAA,oBAS/B,MAAA,OARH,OAAA,EAAA,EAAA,gBAAK,CAAA,mBAAoD,EAAA,aAAA,CAAA,CAI1D,UAAQ,mCAGA,EAAA,OAAA,UAAA,CAAA,CAAA,EAAA,IAAA,EAAA,EAAA,YAAA,EAAA,EAAA,EAAA,oBAWN,IAAA,OAPD,OAAA,EAAA,EAAA,gBAAK,CAAA,mBAAoD,EAAA,aAAA,CAAA,CAI1D,UAAQ,uCAEL,EAAA,KAAI,CAAA,EAAA,EAGD,EAAA,eAAa,GAAA,EAAA,EAAA,YAAA,EAAA,EAAA,EAAA,oBAMZ,SAAA,OALN,OAAA,EAAA,EAAA,gBAAK,CAAA,kBAAsB,EAAA,YAAW,CAAA,CACvC,UAAQ,qCAGc,EAAA,OAAA,SAAA,CAAA,CAAA,EAAA,GAAA,EAAA,EAAA,oBAAA,GAAA,GAAA,CAGf,EAAA,+CAmBG,EAAA,OAdV,MAAM,iBACN,UAAQ,wBACP,KAAM,IACP,KAAK,QACL,WAAW,QACV,aAAY,EAAA,iBACZ,MAAO,EAAA,iBACP,QAAO,EAAA,QAEG,MAAA,EAAA,EAAA,UAGP,CAHe,cAAQ,EAAA,EAAA,EAAA,aAGvB,EAAA,CADC,KAAM,EAAQ,CAAA,KAAA,EAAA,CAAA,OAAA,CAAA,CAAA,CAAA,6CAhBZ,EAAA,EAAA,YAAA,EAAA,EAAA,EAAA,aAEP,EAAA,OADC,QAAO,EAAA,0CA7DF,EAAA,KAAI,CAAA,CAAA,CAAA,CAAA,sEAxCU,EAAA,KAAI,aAAA,GAAA,aAAA,GAAA,CAAA,CAAA,CAAA,CAAA,CAAA,EAAA,CAAA,WAAA,KAAA,CAAA"}
|
package/dist/lib/modal/modal.js
CHANGED
|
@@ -158,9 +158,6 @@ var F = "button:not(:disabled),[href],input:not(:disabled),select:not(:disabled)
|
|
|
158
158
|
};
|
|
159
159
|
},
|
|
160
160
|
computed: {
|
|
161
|
-
hasFooterSlot() {
|
|
162
|
-
return !!this.$slots.footer;
|
|
163
|
-
},
|
|
164
161
|
bannerKindClass() {
|
|
165
162
|
return p[this.bannerKind];
|
|
166
163
|
},
|
|
@@ -188,6 +185,9 @@ var F = "button:not(:disabled),[href],input:not(:disabled),select:not(:disabled)
|
|
|
188
185
|
e?.open && (e.close(), n(this.getScrollRoot())), this.previousActiveElement = null;
|
|
189
186
|
},
|
|
190
187
|
methods: {
|
|
188
|
+
hasFooterSlot() {
|
|
189
|
+
return !!this.$slots.footer;
|
|
190
|
+
},
|
|
191
191
|
getScrollRoot() {
|
|
192
192
|
return a(this.$refs.dialogEl)?.getRootNode()?.host;
|
|
193
193
|
},
|
|
@@ -310,9 +310,10 @@ function z(e, t, n, r, i, a) {
|
|
|
310
310
|
class: w(["d-modal__content", n.contentClass]),
|
|
311
311
|
"data-qa": "dt-modal-copy"
|
|
312
312
|
}, k(n.copy), 3)),
|
|
313
|
-
a.hasFooterSlot ? (T(), y("footer", {
|
|
313
|
+
a.hasFooterSlot() ? (T(), y("footer", {
|
|
314
314
|
key: 4,
|
|
315
|
-
class: w(["d-modal__footer", n.footerClass])
|
|
315
|
+
class: w(["d-modal__footer", n.footerClass]),
|
|
316
|
+
"data-qa": "dt-modal-footer"
|
|
316
317
|
}, [E(e.$slots, "footer")], 2)) : v("", !0),
|
|
317
318
|
n.showClose ? (T(), _(l, {
|
|
318
319
|
key: 6,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"modal.js","names":[],"sources":["../../../components/Modal/Modal.vue"],"sourcesContent":["<template>\n <teleport\n :disabled=\"!appendTo && !autoTeleportTarget\"\n :to=\"appendTo || autoTeleportTarget\"\n >\n <!-- eslint-disable-next-line vuejs-accessibility/no-static-element-interactions -->\n <dialog\n ref=\"dialogEl\"\n v-dt-focustrap=\"{ active: open, initialFocus: false, restoreFocus: false }\"\n :class=\"[\n 'd-modal',\n MODAL_KIND_MODIFIERS[kind],\n { 'd-modal--full': fullscreen },\n { 'd-modal--transparent-backdrop': transparentBackdrop },\n modalClass,\n ]\"\n data-qa=\"dt-modal\"\n :aria-modal=\"modal ? 'true' : undefined\"\n :aria-describedby=\"describedById || undefined\"\n :aria-labelledby=\"labelledById\"\n v-bind=\"modeAttrs\"\n @cancel.prevent=\"close\"\n @mousedown=\"onBackdropMousedown\"\n @mouseup=\"onBackdropMouseup\"\n @click=\"onBackdropClick\"\n @keydown=\"onKeydown\"\n >\n <div\n v-if=\"open && (hasSlotContent($slots.banner) || bannerHeaderText)\"\n data-qa=\"dt-modal-banner\"\n :class=\"[\n 'd-modal__banner',\n bannerClass,\n bannerKindClass,\n ]\"\n >\n <!-- @slot Slot for the banner, defaults to bannerHeaderText prop -->\n <slot name=\"banner\">\n {{ bannerHeaderText }}\n </slot>\n </div>\n <transition\n :appear=\"open\"\n name=\"d-modal__dialog\"\n @after-enter=\"onAfterEnter\"\n @after-leave=\"onAfterLeave\"\n >\n <div\n v-show=\"open\"\n :class=\"[\n 'd-modal__dialog',\n { 'd-modal__dialog--scrollable': fixedHeaderFooter },\n dialogClass,\n ]\"\n >\n <div\n v-if=\"hasSlotContent($slots.header)\"\n :id=\"labelledById\"\n :class=\"['d-modal__header', headerClass]\"\n data-qa=\"dt-modal-title\"\n >\n <!-- @slot Slot for dialog header section, taking the place of any \"headerText\" text prop -->\n <slot name=\"header\" />\n </div>\n <dt-text\n v-else\n :id=\"labelledById\"\n kind=\"headline\"\n :size=\"600\"\n strength=\"medium\"\n density=\"100\"\n text-box-trim=\"start\"\n as=\"h2\"\n :class=\"['d-modal__header', headerClass]\"\n data-qa=\"dt-modal-title\"\n >\n {{ headerText }}\n </dt-text>\n <div\n v-if=\"hasSlotContent($slots.default)\"\n :class=\"[\n 'd-modal__content',\n contentClass,\n ]\"\n data-qa=\"dt-modal-copy\"\n >\n <!-- @slot Default slot for dialog body section, taking the place of any \"copy\" text prop -->\n <slot />\n </div>\n <p\n v-else\n :class=\"[\n 'd-modal__content',\n contentClass,\n ]\"\n data-qa=\"dt-modal-copy\"\n >\n {{ copy }}\n </p>\n <footer\n v-if=\"hasFooterSlot\"\n :class=\"['d-modal__footer', footerClass]\"\n >\n <!-- @slot Slot for dialog footer content, often containing cancel and confirm buttons. -->\n <slot name=\"footer\" />\n </footer>\n <sr-only-close-button\n v-if=\"!showClose\"\n @close=\"close\"\n />\n <dt-button\n v-else\n class=\"d-modal__close\"\n data-qa=\"dt-modal-close-button\"\n :size=\"300\"\n kind=\"muted\"\n importance=\"clear\"\n :aria-label=\"closeButtonTitle\"\n :title=\"closeButtonTitle\"\n @click=\"close\"\n >\n <template #icon=\"{ iconSize }\">\n <dt-icon-close\n :size=\"iconSize\"\n />\n </template>\n </dt-button>\n </div>\n </transition>\n </dialog>\n </teleport>\n</template>\n\n<script>\n/* eslint-disable max-lines */\nimport { DtButton } from '@/components/Button';\nimport { DtText } from '@/components/Text';\nimport { DtIconClose } from '@dialpad/dialtone-icons/vue';\nimport ModeMixin from '@/common/mixins/mode';\nimport {\n MODAL_BANNER_KINDS,\n MODAL_KIND_MODIFIERS,\n} from './ModalConstants';\nimport { getUniqueString, hasSlotContent, returnFirstEl, disableRootScrolling, enableRootScrolling } from '@/common/utils';\nimport { HTML_ELEMENT_TYPE } from '@/common/constants';\nimport SrOnlyCloseButton from '@/common/sr_only_close_button.vue';\nimport { NOTICE_KINDS } from '@/components/Notice';\nimport { DialtoneLocalization } from '@/localization';\n\nconst focusableSelector = 'button:not(:disabled),[href],input:not(:disabled),select:not(:disabled),' +\n 'textarea:not(:disabled),details,[tabindex]:not([tabindex=\"-1\"]):not(:disabled):not([aria-disabled=\"true\"])';\n\n/**\n * Modals focus the user's attention exclusively on one task or piece of information\n * via a window that sits on top of the page content.\n * @see https://dialtone.dialpad.com/components/modal.html\n */\nexport default {\n name: 'DtModal',\n\n components: {\n DtButton,\n DtText,\n DtIconClose,\n SrOnlyCloseButton,\n },\n\n mixins: [ModeMixin],\n\n props: {\n /**\n * Body text to display as the modal's main content.\n */\n copy: {\n type: String,\n default: '',\n },\n\n /**\n * Id to use for the dialog's aria-describedby.\n * Recommended only if the dialog content itself isn't enough to give full context,\n * as screen readers should recite the dialog contents by default before any aria-description.\n */\n describedById: {\n type: String,\n default: '',\n },\n\n /**\n * Id to use for the dialog's aria-labelledby.\n */\n labelledById: {\n type: String,\n default: function () { return getUniqueString(); },\n },\n\n /**\n * Whether the modal should be shown.\n * Parent component can sync on this value to control the modal's visibility.\n * @values true, false\n */\n open: {\n type: Boolean,\n default: false,\n },\n\n /**\n * Header text to display in the modal header.\n */\n headerText: {\n type: String,\n default: undefined,\n },\n\n /**\n * Header text to display in the modal banner.\n */\n bannerHeaderText: {\n type: String,\n default: undefined,\n },\n\n /**\n * The theme of the modal.\n * @values default, critical\n */\n kind: {\n type: String,\n default: 'default',\n validator: (k) => Object.keys(MODAL_KIND_MODIFIERS).includes(k),\n },\n\n /**\n * Whether the modal fills the viewport instead of rendering at its default size.\n * @values true, false\n */\n fullscreen: {\n type: Boolean,\n default: false,\n },\n\n /**\n * Additional class name for the root modal element.\n * Can accept String, Object, and Array, i.e. has the\n * same API as Vue's built-in handling of the class attribute.\n */\n modalClass: {\n type: [String, Object, Array],\n default: '',\n },\n\n /**\n * Additional class name for the dialog element within the modal.\n * Can accept String, Object, and Array, i.e. has the\n * same API as Vue's built-in handling of the class attribute.\n */\n dialogClass: {\n type: [String, Object, Array],\n default: '',\n },\n\n /**\n * Additional class name for the content element within the modal.\n * Can accept String, Object, and Array, i.e. has the\n * same API as Vue's built-in handling of the class attribute.\n */\n contentClass: {\n type: [String, Object, Array],\n default: '',\n },\n\n /**\n * Sets the color of the banner.\n * @values base, critical, info, positive, warning\n */\n bannerKind: {\n type: String,\n default: 'warning',\n validator (kind) {\n return NOTICE_KINDS.includes(kind);\n },\n },\n\n /**\n * Additional class name for the banner element within the modal.\n * Can accept String, Object, and Array, i.e. has the\n * same API as Vue's built-in handling of the class attribute.\n */\n bannerClass: {\n type: [String, Object, Array],\n default: '',\n },\n\n /**\n * Additional class name for the header element within the modal.\n * Can accept String, Object, and Array, i.e. has the\n * same API as Vue's built-in handling of the class attribute.\n */\n headerClass: {\n type: [String, Object, Array],\n default: '',\n },\n\n /**\n * Additional class name for the footer element within the modal.\n * Can accept String, Object, and Array, i.e. has the\n * same API as Vue's built-in handling of the class attribute.\n */\n footerClass: {\n type: [String, Object, Array],\n default: '',\n },\n\n /**\n * Shows the close button on the modal\n * @values true, false\n */\n showClose: {\n type: Boolean,\n default: true,\n },\n\n /**\n * Whether the modal will close when you click outside of the dialog on the overlay.\n * @values true, false\n */\n closeOnClick: {\n type: Boolean,\n default: true,\n },\n\n /**\n * Scrollable modal that allows scroll the modal content keeping the header and footer fixed\n * @values true, false\n */\n fixedHeaderFooter: {\n type: Boolean,\n default: true,\n },\n\n /**\n * The element that is focused when the modal is opened. This can be an\n * HTMLElement within the modal, a string starting with '#' which will\n * find the element by ID. 'first' which will automatically focus\n * the first element, or 'dialog' which will focus the dialog window itself.\n * If the dialog is modal this prop cannot be 'none'.\n */\n initialFocusElement: {\n type: [String, HTML_ELEMENT_TYPE],\n default: 'first',\n validator: initialFocusElement => {\n return initialFocusElement === 'first' ||\n (initialFocusElement instanceof HTMLElement) ||\n initialFocusElement.startsWith('#');\n },\n },\n\n /**\n * A CSS selector string for the element to portal the modal to. If not provided, the modal will be rendered in its default location.\n */\n appendTo: {\n type: String,\n default: undefined,\n },\n\n /**\n * When true, the surrounding backdrop is rendered fully transparent\n * instead of the default dimming overlay. The dialog box itself\n * remains opaque. Useful when the underlying UI should remain visible.\n * @values true, false\n */\n transparentBackdrop: {\n type: Boolean,\n default: false,\n },\n\n /**\n * When true, the dialog opens with showModal(), which promotes it to the browser\n * top layer. Nothing outside the top layer can paint above it regardless of\n * z-index, so application surfaces such as toasts and call notifications end up\n * behind it. When false, it opens with show() and stays in the normal stacking\n * order, where the Dialtone z-index scale applies and --zi-notification (700)\n * outranks --zi-modal (600) as documented.\n *\n * Focus trapping, scroll locking and Esc-to-close behave identically in both\n * modes. Background inertness does not: only the top layer provides it, so with\n * modal unset the page outside the dialog stays reachable. That is deliberate —\n * it is what lets an application's own overlays remain usable above a modal —\n * and keyboard containment still comes from the focus trap.\n * @values true, false\n */\n modal: {\n type: Boolean,\n default: false,\n },\n },\n\n emits: [\n /**\n * Native button click event\n *\n * @event click\n * @type {PointerEvent | KeyboardEvent}\n */\n 'click',\n\n /**\n * Native keydown event\n *\n * @event keydown\n * @type {KeyboardEvent}\n */\n 'keydown',\n\n /**\n * The modal will emit a \"false\" boolean value for this event when the user performs a modal-closing action.\n * Parent components can sync on this value to create a 2-way binding to control modal visibility.\n *\n * @event update:open\n * @type {Boolean}\n */\n 'update:open',\n ],\n\n data () {\n return {\n MODAL_KIND_MODIFIERS,\n MODAL_BANNER_KINDS,\n hasSlotContent,\n i18n: new DialtoneLocalization(),\n autoTeleportTarget: null,\n mousedownOnBackdrop: false,\n mouseupOnBackdrop: false,\n };\n },\n\n computed: {\n hasFooterSlot () {\n return !!this.$slots.footer;\n },\n\n bannerKindClass () {\n return MODAL_BANNER_KINDS[this.bannerKind];\n },\n\n closeButtonTitle () {\n return this.i18n.$t('DIALTONE_CLOSE_BUTTON');\n },\n },\n\n watch: {\n open (isShowing) {\n this.syncDialogState(isShowing);\n },\n },\n\n mounted () {\n if (!this.appendTo) {\n const root = this.$el?.getRootNode();\n if (root instanceof ShadowRoot) {\n this.autoTeleportTarget = root;\n // Defer syncDialogState so the teleport renders inside the shadow root first.\n if (this.open) this.$nextTick(() => { if (this.open) this.syncDialogState(true); });\n return;\n }\n }\n if (this.open) {\n this.syncDialogState(true);\n }\n },\n\n beforeUnmount () {\n const dialogEl = this.$refs.dialogEl;\n if (dialogEl?.open) {\n dialogEl.close();\n enableRootScrolling(this.getScrollRoot());\n }\n this.previousActiveElement = null;\n },\n\n methods: {\n getScrollRoot () {\n return returnFirstEl(this.$refs.dialogEl)?.getRootNode()?.host;\n },\n\n syncDialogState (isShowing) {\n const dialogEl = this.$refs.dialogEl;\n if (!dialogEl) return;\n\n if (isShowing) {\n this.previousActiveElement = document.activeElement;\n if (!dialogEl.open) {\n // show() leaves the dialog in the normal stacking order instead of the\n // top layer, where the z-index scale still applies.\n if (this.modal) dialogEl.showModal(); else dialogEl.show();\n }\n disableRootScrolling(this.getScrollRoot());\n } else if (dialogEl.open) {\n // Leave transition plays via v-show on inner content.\n // close() is called in onAfterLeave when transition completes.\n enableRootScrolling(this.getScrollRoot());\n }\n },\n\n\n\n close () {\n this.$emit('update:open', false);\n },\n\n onBackdropMousedown (event) {\n this.mousedownOnBackdrop = event.target === event.currentTarget;\n },\n\n onBackdropMouseup (event) {\n this.mouseupOnBackdrop = event.target === event.currentTarget;\n },\n\n onBackdropClick (event) {\n const pressedAndReleasedOnBackdrop = this.mousedownOnBackdrop && this.mouseupOnBackdrop;\n if (this.closeOnClick && event.target === event.currentTarget && pressedAndReleasedOnBackdrop) {\n this.close();\n }\n this.$emit('click', event);\n },\n\n onKeydown (event) {\n // The native cancel event only fires for dialogs opened with showModal(), so\n // Esc has to be handled explicitly to keep dismissal identical in both modes.\n // defaultPrevented means a nested widget (dropdown, combobox) already consumed\n // it to close itself, and the modal must not close out from under it.\n if (!this.modal && event.key === 'Escape' && !event.defaultPrevented) {\n event.preventDefault();\n this.close();\n }\n this.$emit('keydown', event);\n },\n\n async onAfterEnter () {\n this.$emit('update:open', true);\n await this.setFocusAfterTransition();\n },\n\n onAfterLeave () {\n const dialogEl = this.$refs.dialogEl;\n if (dialogEl?.open) {\n dialogEl.close();\n }\n this.previousActiveElement?.focus();\n this.previousActiveElement = null;\n },\n\n focusFirstTabbable (container) {\n const focusable = [...container.querySelectorAll(focusableSelector)];\n if (!focusable.length) return;\n let target = focusable[0];\n // If first focusable is an unchecked radio, prefer the checked radio in the same group.\n if (target.matches('[type=\"radio\"]:not(:checked)')) {\n target = focusable.find(el => el.checked && el.name === target.name) || target;\n }\n target.focus({ preventScroll: true });\n },\n\n async setFocusAfterTransition () {\n const dialogEl = this.$refs.dialogEl;\n if (!dialogEl) return;\n\n await this.$nextTick();\n\n if (this.initialFocusElement === 'first') {\n this.focusFirstTabbable(dialogEl);\n } else if (typeof this.initialFocusElement === 'string' && this.initialFocusElement.startsWith('#')) {\n const el = dialogEl.querySelector(this.initialFocusElement);\n if (el) {\n el.focus();\n } else {\n // eslint-disable-next-line no-console\n console.warn('Could not find the element specified in dt-modal prop \"initialFocusElement\". ' +\n 'Defaulting to focusing the first element.');\n this.focusFirstTabbable(dialogEl);\n }\n } else if (this.initialFocusElement instanceof HTMLElement) {\n this.initialFocusElement.focus();\n }\n },\n },\n};\n</script>\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"modal.js","names":[],"sources":["../../../components/Modal/Modal.vue"],"sourcesContent":["<template>\n <teleport\n :disabled=\"!appendTo && !autoTeleportTarget\"\n :to=\"appendTo || autoTeleportTarget\"\n >\n <!-- eslint-disable-next-line vuejs-accessibility/no-static-element-interactions -->\n <dialog\n ref=\"dialogEl\"\n v-dt-focustrap=\"{ active: open, initialFocus: false, restoreFocus: false }\"\n :class=\"[\n 'd-modal',\n MODAL_KIND_MODIFIERS[kind],\n { 'd-modal--full': fullscreen },\n { 'd-modal--transparent-backdrop': transparentBackdrop },\n modalClass,\n ]\"\n data-qa=\"dt-modal\"\n :aria-modal=\"modal ? 'true' : undefined\"\n :aria-describedby=\"describedById || undefined\"\n :aria-labelledby=\"labelledById\"\n v-bind=\"modeAttrs\"\n @cancel.prevent=\"close\"\n @mousedown=\"onBackdropMousedown\"\n @mouseup=\"onBackdropMouseup\"\n @click=\"onBackdropClick\"\n @keydown=\"onKeydown\"\n >\n <div\n v-if=\"open && (hasSlotContent($slots.banner) || bannerHeaderText)\"\n data-qa=\"dt-modal-banner\"\n :class=\"[\n 'd-modal__banner',\n bannerClass,\n bannerKindClass,\n ]\"\n >\n <!-- @slot Slot for the banner, defaults to bannerHeaderText prop -->\n <slot name=\"banner\">\n {{ bannerHeaderText }}\n </slot>\n </div>\n <transition\n :appear=\"open\"\n name=\"d-modal__dialog\"\n @after-enter=\"onAfterEnter\"\n @after-leave=\"onAfterLeave\"\n >\n <div\n v-show=\"open\"\n :class=\"[\n 'd-modal__dialog',\n { 'd-modal__dialog--scrollable': fixedHeaderFooter },\n dialogClass,\n ]\"\n >\n <div\n v-if=\"hasSlotContent($slots.header)\"\n :id=\"labelledById\"\n :class=\"['d-modal__header', headerClass]\"\n data-qa=\"dt-modal-title\"\n >\n <!-- @slot Slot for dialog header section, taking the place of any \"headerText\" text prop -->\n <slot name=\"header\" />\n </div>\n <dt-text\n v-else\n :id=\"labelledById\"\n kind=\"headline\"\n :size=\"600\"\n strength=\"medium\"\n density=\"100\"\n text-box-trim=\"start\"\n as=\"h2\"\n :class=\"['d-modal__header', headerClass]\"\n data-qa=\"dt-modal-title\"\n >\n {{ headerText }}\n </dt-text>\n <div\n v-if=\"hasSlotContent($slots.default)\"\n :class=\"[\n 'd-modal__content',\n contentClass,\n ]\"\n data-qa=\"dt-modal-copy\"\n >\n <!-- @slot Default slot for dialog body section, taking the place of any \"copy\" text prop -->\n <slot />\n </div>\n <p\n v-else\n :class=\"[\n 'd-modal__content',\n contentClass,\n ]\"\n data-qa=\"dt-modal-copy\"\n >\n {{ copy }}\n </p>\n <footer\n v-if=\"hasFooterSlot()\"\n :class=\"['d-modal__footer', footerClass]\"\n data-qa=\"dt-modal-footer\"\n >\n <!-- @slot Slot for dialog footer content, often containing cancel and confirm buttons. -->\n <slot name=\"footer\" />\n </footer>\n <sr-only-close-button\n v-if=\"!showClose\"\n @close=\"close\"\n />\n <dt-button\n v-else\n class=\"d-modal__close\"\n data-qa=\"dt-modal-close-button\"\n :size=\"300\"\n kind=\"muted\"\n importance=\"clear\"\n :aria-label=\"closeButtonTitle\"\n :title=\"closeButtonTitle\"\n @click=\"close\"\n >\n <template #icon=\"{ iconSize }\">\n <dt-icon-close\n :size=\"iconSize\"\n />\n </template>\n </dt-button>\n </div>\n </transition>\n </dialog>\n </teleport>\n</template>\n\n<script>\n/* eslint-disable max-lines */\nimport { DtButton } from '@/components/Button';\nimport { DtText } from '@/components/Text';\nimport { DtIconClose } from '@dialpad/dialtone-icons/vue';\nimport ModeMixin from '@/common/mixins/mode';\nimport {\n MODAL_BANNER_KINDS,\n MODAL_KIND_MODIFIERS,\n} from './ModalConstants';\nimport { getUniqueString, hasSlotContent, returnFirstEl, disableRootScrolling, enableRootScrolling } from '@/common/utils';\nimport { HTML_ELEMENT_TYPE } from '@/common/constants';\nimport SrOnlyCloseButton from '@/common/sr_only_close_button.vue';\nimport { NOTICE_KINDS } from '@/components/Notice';\nimport { DialtoneLocalization } from '@/localization';\n\nconst focusableSelector = 'button:not(:disabled),[href],input:not(:disabled),select:not(:disabled),' +\n 'textarea:not(:disabled),details,[tabindex]:not([tabindex=\"-1\"]):not(:disabled):not([aria-disabled=\"true\"])';\n\n/**\n * Modals focus the user's attention exclusively on one task or piece of information\n * via a window that sits on top of the page content.\n * @see https://dialtone.dialpad.com/components/modal.html\n */\nexport default {\n name: 'DtModal',\n\n components: {\n DtButton,\n DtText,\n DtIconClose,\n SrOnlyCloseButton,\n },\n\n mixins: [ModeMixin],\n\n props: {\n /**\n * Body text to display as the modal's main content.\n */\n copy: {\n type: String,\n default: '',\n },\n\n /**\n * Id to use for the dialog's aria-describedby.\n * Recommended only if the dialog content itself isn't enough to give full context,\n * as screen readers should recite the dialog contents by default before any aria-description.\n */\n describedById: {\n type: String,\n default: '',\n },\n\n /**\n * Id to use for the dialog's aria-labelledby.\n */\n labelledById: {\n type: String,\n default: function () { return getUniqueString(); },\n },\n\n /**\n * Whether the modal should be shown.\n * Parent component can sync on this value to control the modal's visibility.\n * @values true, false\n */\n open: {\n type: Boolean,\n default: false,\n },\n\n /**\n * Header text to display in the modal header.\n */\n headerText: {\n type: String,\n default: undefined,\n },\n\n /**\n * Header text to display in the modal banner.\n */\n bannerHeaderText: {\n type: String,\n default: undefined,\n },\n\n /**\n * The theme of the modal.\n * @values default, critical\n */\n kind: {\n type: String,\n default: 'default',\n validator: (k) => Object.keys(MODAL_KIND_MODIFIERS).includes(k),\n },\n\n /**\n * Whether the modal fills the viewport instead of rendering at its default size.\n * @values true, false\n */\n fullscreen: {\n type: Boolean,\n default: false,\n },\n\n /**\n * Additional class name for the root modal element.\n * Can accept String, Object, and Array, i.e. has the\n * same API as Vue's built-in handling of the class attribute.\n */\n modalClass: {\n type: [String, Object, Array],\n default: '',\n },\n\n /**\n * Additional class name for the dialog element within the modal.\n * Can accept String, Object, and Array, i.e. has the\n * same API as Vue's built-in handling of the class attribute.\n */\n dialogClass: {\n type: [String, Object, Array],\n default: '',\n },\n\n /**\n * Additional class name for the content element within the modal.\n * Can accept String, Object, and Array, i.e. has the\n * same API as Vue's built-in handling of the class attribute.\n */\n contentClass: {\n type: [String, Object, Array],\n default: '',\n },\n\n /**\n * Sets the color of the banner.\n * @values base, critical, info, positive, warning\n */\n bannerKind: {\n type: String,\n default: 'warning',\n validator (kind) {\n return NOTICE_KINDS.includes(kind);\n },\n },\n\n /**\n * Additional class name for the banner element within the modal.\n * Can accept String, Object, and Array, i.e. has the\n * same API as Vue's built-in handling of the class attribute.\n */\n bannerClass: {\n type: [String, Object, Array],\n default: '',\n },\n\n /**\n * Additional class name for the header element within the modal.\n * Can accept String, Object, and Array, i.e. has the\n * same API as Vue's built-in handling of the class attribute.\n */\n headerClass: {\n type: [String, Object, Array],\n default: '',\n },\n\n /**\n * Additional class name for the footer element within the modal.\n * Can accept String, Object, and Array, i.e. has the\n * same API as Vue's built-in handling of the class attribute.\n */\n footerClass: {\n type: [String, Object, Array],\n default: '',\n },\n\n /**\n * Shows the close button on the modal\n * @values true, false\n */\n showClose: {\n type: Boolean,\n default: true,\n },\n\n /**\n * Whether the modal will close when you click outside of the dialog on the overlay.\n * @values true, false\n */\n closeOnClick: {\n type: Boolean,\n default: true,\n },\n\n /**\n * Scrollable modal that allows scroll the modal content keeping the header and footer fixed\n * @values true, false\n */\n fixedHeaderFooter: {\n type: Boolean,\n default: true,\n },\n\n /**\n * The element that is focused when the modal is opened. This can be an\n * HTMLElement within the modal, a string starting with '#' which will\n * find the element by ID. 'first' which will automatically focus\n * the first element, or 'dialog' which will focus the dialog window itself.\n * If the dialog is modal this prop cannot be 'none'.\n */\n initialFocusElement: {\n type: [String, HTML_ELEMENT_TYPE],\n default: 'first',\n validator: initialFocusElement => {\n return initialFocusElement === 'first' ||\n (initialFocusElement instanceof HTMLElement) ||\n initialFocusElement.startsWith('#');\n },\n },\n\n /**\n * A CSS selector string for the element to portal the modal to. If not provided, the modal will be rendered in its default location.\n */\n appendTo: {\n type: String,\n default: undefined,\n },\n\n /**\n * When true, the surrounding backdrop is rendered fully transparent\n * instead of the default dimming overlay. The dialog box itself\n * remains opaque. Useful when the underlying UI should remain visible.\n * @values true, false\n */\n transparentBackdrop: {\n type: Boolean,\n default: false,\n },\n\n /**\n * When true, the dialog opens with showModal(), which promotes it to the browser\n * top layer. Nothing outside the top layer can paint above it regardless of\n * z-index, so application surfaces such as toasts and call notifications end up\n * behind it. When false, it opens with show() and stays in the normal stacking\n * order, where the Dialtone z-index scale applies and --zi-notification (700)\n * outranks --zi-modal (600) as documented.\n *\n * Focus trapping, scroll locking and Esc-to-close behave identically in both\n * modes. Background inertness does not: only the top layer provides it, so with\n * modal unset the page outside the dialog stays reachable. That is deliberate —\n * it is what lets an application's own overlays remain usable above a modal —\n * and keyboard containment still comes from the focus trap.\n * @values true, false\n */\n modal: {\n type: Boolean,\n default: false,\n },\n },\n\n emits: [\n /**\n * Native button click event\n *\n * @event click\n * @type {PointerEvent | KeyboardEvent}\n */\n 'click',\n\n /**\n * Native keydown event\n *\n * @event keydown\n * @type {KeyboardEvent}\n */\n 'keydown',\n\n /**\n * The modal will emit a \"false\" boolean value for this event when the user performs a modal-closing action.\n * Parent components can sync on this value to create a 2-way binding to control modal visibility.\n *\n * @event update:open\n * @type {Boolean}\n */\n 'update:open',\n ],\n\n data () {\n return {\n MODAL_KIND_MODIFIERS,\n MODAL_BANNER_KINDS,\n hasSlotContent,\n i18n: new DialtoneLocalization(),\n autoTeleportTarget: null,\n mousedownOnBackdrop: false,\n mouseupOnBackdrop: false,\n };\n },\n\n computed: {\n bannerKindClass () {\n return MODAL_BANNER_KINDS[this.bannerKind];\n },\n\n closeButtonTitle () {\n return this.i18n.$t('DIALTONE_CLOSE_BUTTON');\n },\n },\n\n watch: {\n open (isShowing) {\n this.syncDialogState(isShowing);\n },\n },\n\n mounted () {\n if (!this.appendTo) {\n const root = this.$el?.getRootNode();\n if (root instanceof ShadowRoot) {\n this.autoTeleportTarget = root;\n // Defer syncDialogState so the teleport renders inside the shadow root first.\n if (this.open) this.$nextTick(() => { if (this.open) this.syncDialogState(true); });\n return;\n }\n }\n if (this.open) {\n this.syncDialogState(true);\n }\n },\n\n beforeUnmount () {\n const dialogEl = this.$refs.dialogEl;\n if (dialogEl?.open) {\n dialogEl.close();\n enableRootScrolling(this.getScrollRoot());\n }\n this.previousActiveElement = null;\n },\n\n methods: {\n // Reads $slots, which is not reactive, so it must not be cached as a computed.\n hasFooterSlot () {\n return !!this.$slots.footer;\n },\n\n getScrollRoot () {\n return returnFirstEl(this.$refs.dialogEl)?.getRootNode()?.host;\n },\n\n syncDialogState (isShowing) {\n const dialogEl = this.$refs.dialogEl;\n if (!dialogEl) return;\n\n if (isShowing) {\n this.previousActiveElement = document.activeElement;\n if (!dialogEl.open) {\n // show() leaves the dialog in the normal stacking order instead of the\n // top layer, where the z-index scale still applies.\n if (this.modal) dialogEl.showModal(); else dialogEl.show();\n }\n disableRootScrolling(this.getScrollRoot());\n } else if (dialogEl.open) {\n // Leave transition plays via v-show on inner content.\n // close() is called in onAfterLeave when transition completes.\n enableRootScrolling(this.getScrollRoot());\n }\n },\n\n\n\n close () {\n this.$emit('update:open', false);\n },\n\n onBackdropMousedown (event) {\n this.mousedownOnBackdrop = event.target === event.currentTarget;\n },\n\n onBackdropMouseup (event) {\n this.mouseupOnBackdrop = event.target === event.currentTarget;\n },\n\n onBackdropClick (event) {\n const pressedAndReleasedOnBackdrop = this.mousedownOnBackdrop && this.mouseupOnBackdrop;\n if (this.closeOnClick && event.target === event.currentTarget && pressedAndReleasedOnBackdrop) {\n this.close();\n }\n this.$emit('click', event);\n },\n\n onKeydown (event) {\n // The native cancel event only fires for dialogs opened with showModal(), so\n // Esc has to be handled explicitly to keep dismissal identical in both modes.\n // defaultPrevented means a nested widget (dropdown, combobox) already consumed\n // it to close itself, and the modal must not close out from under it.\n if (!this.modal && event.key === 'Escape' && !event.defaultPrevented) {\n event.preventDefault();\n this.close();\n }\n this.$emit('keydown', event);\n },\n\n async onAfterEnter () {\n this.$emit('update:open', true);\n await this.setFocusAfterTransition();\n },\n\n onAfterLeave () {\n const dialogEl = this.$refs.dialogEl;\n if (dialogEl?.open) {\n dialogEl.close();\n }\n this.previousActiveElement?.focus();\n this.previousActiveElement = null;\n },\n\n focusFirstTabbable (container) {\n const focusable = [...container.querySelectorAll(focusableSelector)];\n if (!focusable.length) return;\n let target = focusable[0];\n // If first focusable is an unchecked radio, prefer the checked radio in the same group.\n if (target.matches('[type=\"radio\"]:not(:checked)')) {\n target = focusable.find(el => el.checked && el.name === target.name) || target;\n }\n target.focus({ preventScroll: true });\n },\n\n async setFocusAfterTransition () {\n const dialogEl = this.$refs.dialogEl;\n if (!dialogEl) return;\n\n await this.$nextTick();\n\n if (this.initialFocusElement === 'first') {\n this.focusFirstTabbable(dialogEl);\n } else if (typeof this.initialFocusElement === 'string' && this.initialFocusElement.startsWith('#')) {\n const el = dialogEl.querySelector(this.initialFocusElement);\n if (el) {\n el.focus();\n } else {\n // eslint-disable-next-line no-console\n console.warn('Could not find the element specified in dt-modal prop \"initialFocusElement\". ' +\n 'Defaulting to focusing the first element.');\n this.focusFirstTabbable(dialogEl);\n }\n } else if (this.initialFocusElement instanceof HTMLElement) {\n this.initialFocusElement.focus();\n }\n },\n },\n};\n</script>\n"],"mappings":";;;;;;;;;;;;;AAsJA,IAAM,IAAoB,0LAQrB,IAAU;CACb,MAAM;CAEN,YAAY;EACV,UAAA;EACA,QAAA;EACA;EACA,mBAAA;EACD;CAED,QAAQ,CAAC,EAAU;CAEnB,OAAO;EAIL,MAAM;GACJ,MAAM;GACN,SAAS;GACV;EAOD,eAAe;GACb,MAAM;GACN,SAAS;GACV;EAKD,cAAc;GACZ,MAAM;GACN,SAAS,WAAY;AAAE,WAAO,GAAiB;;GAChD;EAOD,MAAM;GACJ,MAAM;GACN,SAAS;GACV;EAKD,YAAY;GACV,MAAM;GACN,SAAS,KAAA;GACV;EAKD,kBAAkB;GAChB,MAAM;GACN,SAAS,KAAA;GACV;EAMD,MAAM;GACJ,MAAM;GACN,SAAS;GACT,YAAY,MAAM,OAAO,KAAK,EAAqB,CAAC,SAAS,EAAE;GAChE;EAMD,YAAY;GACV,MAAM;GACN,SAAS;GACV;EAOD,YAAY;GACV,MAAM;IAAC;IAAQ;IAAQ;IAAM;GAC7B,SAAS;GACV;EAOD,aAAa;GACX,MAAM;IAAC;IAAQ;IAAQ;IAAM;GAC7B,SAAS;GACV;EAOD,cAAc;GACZ,MAAM;IAAC;IAAQ;IAAQ;IAAM;GAC7B,SAAS;GACV;EAMD,YAAY;GACV,MAAM;GACN,SAAS;GACT,UAAW,GAAM;AACf,WAAO,EAAa,SAAS,EAAK;;GAErC;EAOD,aAAa;GACX,MAAM;IAAC;IAAQ;IAAQ;IAAM;GAC7B,SAAS;GACV;EAOD,aAAa;GACX,MAAM;IAAC;IAAQ;IAAQ;IAAM;GAC7B,SAAS;GACV;EAOD,aAAa;GACX,MAAM;IAAC;IAAQ;IAAQ;IAAM;GAC7B,SAAS;GACV;EAMD,WAAW;GACT,MAAM;GACN,SAAS;GACV;EAMD,cAAc;GACZ,MAAM;GACN,SAAS;GACV;EAMD,mBAAmB;GACjB,MAAM;GACN,SAAS;GACV;EASD,qBAAqB;GACnB,MAAM,CAAC,QAAQ,EAAkB;GACjC,SAAS;GACT,YAAW,MACF,MAAwB,WAC5B,aAA+B,eAChC,EAAoB,WAAW,IAAI;GAExC;EAKD,UAAU;GACR,MAAM;GACN,SAAS,KAAA;GACV;EAQD,qBAAqB;GACnB,MAAM;GACN,SAAS;GACV;EAiBD,OAAO;GACL,MAAM;GACN,SAAS;GACV;EACF;CAED,OAAO;EAOL;EAQA;EASA;EACD;CAED,OAAQ;AACN,SAAO;GACL;GACA;GACA;GACA,MAAM,IAAI,GAAsB;GAChC,oBAAoB;GACpB,qBAAqB;GACrB,mBAAmB;GACpB;;CAGH,UAAU;EACR,kBAAmB;AACjB,UAAO,EAAmB,KAAK;;EAGjC,mBAAoB;AAClB,UAAO,KAAK,KAAK,GAAG,wBAAwB;;EAE/C;CAED,OAAO,EACL,KAAM,GAAW;AACf,OAAK,gBAAgB,EAAU;IAElC;CAED,UAAW;AACT,MAAI,CAAC,KAAK,UAAU;GAClB,IAAM,IAAO,KAAK,KAAK,aAAa;AACpC,OAAI,aAAgB,YAAY;AAG9B,IAFA,KAAK,qBAAqB,GAEtB,KAAK,QAAM,KAAK,gBAAgB;AAAE,KAAI,KAAK,QAAM,KAAK,gBAAgB,GAAK;MAAI;AACnF;;;AAGJ,EAAI,KAAK,QACP,KAAK,gBAAgB,GAAK;;CAI9B,gBAAiB;EACf,IAAM,IAAW,KAAK,MAAM;AAK5B,EAJI,GAAU,SACZ,EAAS,OAAO,EAChB,EAAoB,KAAK,eAAe,CAAC,GAE3C,KAAK,wBAAwB;;CAG/B,SAAS;EAEP,gBAAiB;AACf,UAAO,CAAC,CAAC,KAAK,OAAO;;EAGvB,gBAAiB;AACf,UAAO,EAAc,KAAK,MAAM,SAAS,EAAE,aAAa,EAAE;;EAG5D,gBAAiB,GAAW;GAC1B,IAAM,IAAW,KAAK,MAAM;AACvB,SAED,KACF,KAAK,wBAAwB,SAAS,eACjC,EAAS,SAGR,KAAK,QAAO,EAAS,WAAW,GAAO,EAAS,MAAM,GAE5D,EAAqB,KAAK,eAAe,CAAC,IACjC,EAAS,QAGlB,EAAoB,KAAK,eAAe,CAAC;;EAM7C,QAAS;AACP,QAAK,MAAM,eAAe,GAAM;;EAGlC,oBAAqB,GAAO;AAC1B,QAAK,sBAAsB,EAAM,WAAW,EAAM;;EAGpD,kBAAmB,GAAO;AACxB,QAAK,oBAAoB,EAAM,WAAW,EAAM;;EAGlD,gBAAiB,GAAO;GACtB,IAAM,IAA+B,KAAK,uBAAuB,KAAK;AAItE,GAHI,KAAK,gBAAgB,EAAM,WAAW,EAAM,iBAAiB,KAC/D,KAAK,OAAO,EAEd,KAAK,MAAM,SAAS,EAAM;;EAG5B,UAAW,GAAO;AAShB,GAJI,CAAC,KAAK,SAAS,EAAM,QAAQ,YAAY,CAAC,EAAM,qBAClD,EAAM,gBAAgB,EACtB,KAAK,OAAO,GAEd,KAAK,MAAM,WAAW,EAAM;;EAG9B,MAAM,eAAgB;AAEpB,GADA,KAAK,MAAM,eAAe,GAAK,EAC/B,MAAM,KAAK,yBAAyB;;EAGtC,eAAgB;GACd,IAAM,IAAW,KAAK,MAAM;AAK5B,GAJI,GAAU,QACZ,EAAS,OAAO,EAElB,KAAK,uBAAuB,OAAO,EACnC,KAAK,wBAAwB;;EAG/B,mBAAoB,GAAW;GAC7B,IAAM,IAAY,CAAC,GAAG,EAAU,iBAAiB,EAAkB,CAAC;AACpE,OAAI,CAAC,EAAU,OAAQ;GACvB,IAAI,IAAS,EAAU;AAKvB,GAHI,EAAO,QAAQ,iCAA+B,KAChD,IAAS,EAAU,MAAK,MAAM,EAAG,WAAW,EAAG,SAAS,EAAO,KAAI,IAAK,IAE1E,EAAO,MAAM,EAAE,eAAe,IAAM,CAAC;;EAGvC,MAAM,0BAA2B;GAC/B,IAAM,IAAW,KAAK,MAAM;AACvB,SAIL,KAFA,MAAM,KAAK,WAAW,EAElB,KAAK,wBAAwB,QAC/B,MAAK,mBAAmB,EAAS;YACxB,OAAO,KAAK,uBAAwB,YAAY,KAAK,oBAAoB,WAAW,IAAI,EAAE;IACnG,IAAM,IAAK,EAAS,cAAc,KAAK,oBAAoB;AAC3D,IAAI,IACF,EAAG,OAAO,IAGV,QAAQ,KAAK,2HACiC,EAC9C,KAAK,mBAAmB,EAAS;UAE1B,KAAK,+BAA+B,eAC7C,KAAK,oBAAoB,OAAO;;EAGrC;CACF;;;;;;;aA3kBC,EAkIW,GAAA;EAjIR,UAAQ,CAAG,EAAA,YAAQ,CAAK,EAAA;EACxB,IAAI,EAAA,YAAY,EAAA;aAGjB,EA4HS,UA5HT,EA4HS;EA3HP,KAAI;EAEH,OAAK;;GAA+B,EAAA,qBAAqB,EAAA;sBAAkC,EAAA,YAAU;sCAA+C,EAAA,qBAAmB;GAAY,EAAA;;EAOpL,WAAQ;EACP,cAAY,EAAA,QAAK,SAAY,KAAA;EAC7B,oBAAkB,EAAA,iBAAiB,KAAA;EACnC,mBAAiB,EAAA;IACV,EAAA,WAAS;EAChB,UAAM,EAAA,OAAA,EAAA,KAAA,GAAA,GAAA,MAAU,EAAA,SAAA,EAAA,MAAA,GAAA,EAAK,EAAA,CAAA,UAAA,CAAA;EACrB,aAAS,EAAA,OAAA,EAAA,MAAA,GAAA,MAAE,EAAA,uBAAA,EAAA,oBAAA,GAAA,EAAmB;EAC9B,WAAO,EAAA,OAAA,EAAA,MAAA,GAAA,MAAE,EAAA,qBAAA,EAAA,kBAAA,GAAA,EAAiB;EAC1B,SAAK,EAAA,OAAA,EAAA,MAAA,GAAA,MAAE,EAAA,mBAAA,EAAA,gBAAA,GAAA,EAAe;EACtB,WAAO,EAAA,OAAA,EAAA,MAAA,GAAA,MAAE,EAAA,aAAA,EAAA,UAAA,GAAA,EAAS;MAGX,EAAA,SAAS,EAAA,eAAe,EAAA,OAAO,OAAM,IAAK,EAAA,qBAAA,GAAA,EADlD,EAaM,OAAA;;EAXJ,WAAQ;EACP,OAAK,EAAA;;GAA2C,EAAA;GAAuB,EAAA;;KAOxE,EAEO,EAAA,QAAA,UAAA,EAAA,QAAA,CAAA,EAAA,EADF,EAAA,iBAAgB,EAAA,EAAA,CAAA,CAAA,CAAA,EAAA,EAAA,IAAA,EAAA,IAAA,GAAA,EAGvB,EAwFa,GAAA;EAvFV,QAAQ,EAAA;EACT,MAAK;EACJ,cAAa,EAAA;EACb,cAAa,EAAA;;mBAmFR,CAAA,EAjFN,EAiFM,OAAA,EA/EH,OAAK,EAAA;;oCAAgF,EAAA,mBAAiB;GAAgB,EAAA;;GAO/G,EAAA,eAAe,EAAA,OAAO,OAAM,IAAA,GAAA,EADpC,EAQM,OAAA;;IANH,IAAI,EAAA;IACJ,OAAK,EAAA,CAAA,mBAAsB,EAAA,YAAW,CAAA;IACvC,WAAQ;OAGR,EAAsB,EAAA,QAAA,SAAA,CAAA,EAAA,IAAA,EAAA,KAAA,GAAA,EAExB,EAaU,GAAA;;IAXP,IAAI,EAAA;IACL,MAAK;IACJ,MAAM;IACP,UAAS;IACT,SAAQ;IACR,iBAAc;IACd,IAAG;IACF,OAAK,EAAA,CAAA,mBAAsB,EAAA,YAAW,CAAA;IACvC,WAAQ;;qBAEQ,CAAA,EAAA,EAAb,EAAA,WAAU,EAAA,EAAA,CAAA,CAAA;;;GAGP,EAAA,eAAe,EAAA,OAAO,QAAO,IAAA,GAAA,EADrC,EAUM,OAAA;;IARH,OAAK,EAAA,CAAA,oBAAoD,EAAA,aAAA,CAAA;IAI1D,WAAQ;OAGR,EAAQ,EAAA,QAAA,UAAA,CAAA,EAAA,EAAA,KAAA,GAAA,EAEV,EASI,KAAA;;IAPD,OAAK,EAAA,CAAA,oBAAoD,EAAA,aAAA,CAAA;IAI1D,WAAQ;QAEL,EAAA,KAAI,EAAA,EAAA;GAGD,EAAA,eAAa,IAAA,GAAA,EADrB,EAOS,UAAA;;IALN,OAAK,EAAA,CAAA,mBAAsB,EAAA,YAAW,CAAA;IACvC,WAAQ;OAGR,EAAsB,EAAA,QAAA,SAAA,CAAA,EAAA,EAAA,IAAA,EAAA,IAAA,GAAA;GAGf,EAAA,kBAGT,EAgBY,GAAA;;IAdV,OAAM;IACN,WAAQ;IACP,MAAM;IACP,MAAK;IACL,YAAW;IACV,cAAY,EAAA;IACZ,OAAO,EAAA;IACP,SAAO,EAAA;;IAEG,MAAI,GAGX,EAHe,kBAAQ,CACzB,EAEE,GAAA,EADC,MAAM,GAAQ,EAAA,MAAA,GAAA,CAAA,OAAA,CAAA,CAAA,CAAA;;;;;;UAhBZ,GAAA,EADT,EAGE,GAAA;;IADC,SAAO,EAAA;;cA7DF,EAAA,KAAI,CAAA,CAAA,CAAA,CAAA;;;;;;;UAxCU,EAAA;EAAI,cAAA;EAAA,cAAA;EAAA,CAAA,CAAA,CAAA,CAAA,EAAA,GAAA,CAAA,YAAA,KAAA,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`../../RichTextEditor-
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`../../RichTextEditor-DMUDJKVn.cjs`),t=require(`./rich-text-editor-constants.cjs`);exports.DtRichTextEditor=e.t,exports.RICH_TEXT_EDITOR_AUTOFOCUS_TYPES=t.RICH_TEXT_EDITOR_AUTOFOCUS_TYPES,exports.RICH_TEXT_EDITOR_OUTPUT_FORMATS=t.RICH_TEXT_EDITOR_OUTPUT_FORMATS;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { t as e } from "../../RichTextEditor-
|
|
1
|
+
import { t as e } from "../../RichTextEditor-D8DfONFm.js";
|
|
2
2
|
import { RICH_TEXT_EDITOR_AUTOFOCUS_TYPES as t, RICH_TEXT_EDITOR_OUTPUT_FORMATS as n } from "./rich-text-editor-constants.js";
|
|
3
3
|
export { e as DtRichTextEditor, t as RICH_TEXT_EDITOR_AUTOFOCUS_TYPES, n as RICH_TEXT_EDITOR_OUTPUT_FORMATS };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}});const e=require(`../../RichTextEditor-
|
|
1
|
+
Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}});const e=require(`../../RichTextEditor-DMUDJKVn.cjs`);exports.default=e.t;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as e } from "../../RichTextEditor-
|
|
1
|
+
import { t as e } from "../../RichTextEditor-D8DfONFm.js";
|
|
2
2
|
export { e as default };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"segmented-control-item.cjs","names":["$attrs","$slots"],"sources":["../../../components/SegmentedControl/SegmentedControlItem.vue"],"sourcesContent":["<template>\n <dt-button\n class=\"d-segmented-control__item\"\n role=\"radio\"\n :aria-checked=\"String(isSelected)\"\n :tabindex=\"isSelected && !isDisabled ? '0' : '-1'\"\n :active=\"isSelected\"\n :disabled=\"isDisabled\"\n :aria-disabled=\"isDisabled ? 'true' : undefined\"\n :aria-label=\"label\"\n :label-class=\"resolvedLabelClass\"\n :data-value=\"value\"\n kind=\"muted\"\n importance=\"clear\"\n :size=\"buttonSize\"\n data-qa=\"dt-segmented-control-item\"\n v-bind=\"$attrs\"\n @click=\"handleClick\"\n @focus=\"handleFocus\"\n >\n <template\n v-if=\"$slots.startIcon\"\n #startIcon=\"{ iconSize }\"\n >\n <!-- @slot Icon displayed at the inline-start of the label. Provides { iconSize } scoped binding. -->\n <slot\n name=\"startIcon\"\n :icon-size=\"iconSize\"\n />\n </template>\n <template\n v-if=\"$slots.endIcon\"\n #endIcon=\"{ iconSize }\"\n >\n <!-- @slot Icon displayed at the inline-end of the label. Provides { iconSize } scoped binding. -->\n <slot\n name=\"endIcon\"\n :icon-size=\"iconSize\"\n />\n </template>\n <template\n v-if=\"$slots.leading\"\n #leading\n >\n <!-- @slot Content rendered before the label (e.g. badges, indicators). -->\n <slot name=\"leading\" />\n </template>\n <template\n v-if=\"$slots.trailing\"\n #trailing\n >\n <!-- @slot Content rendered after the label (e.g. badges, counts). -->\n <slot name=\"trailing\" />\n </template>\n <!-- @slot Label text content -->\n <slot />\n </dt-button>\n</template>\n\n<script setup>\nimport { computed, inject } from 'vue';\nimport { DtButton } from '@/components/Button';\nimport {\n SEGMENTED_CONTROL_CONTEXT_KEY,\n SEGMENTED_CONTROL_SELECT_KEY,\n SEGMENTED_CONTROL_FOCUS_KEY,\n SEGMENTED_CONTROL_SIZE_DEFAULT,\n} from './SegmentedControlConstants.js';\n\ndefineOptions({\n name: 'DtSegmentedControlItem',\n inheritAttrs: false,\n});\n\nconst props = defineProps({\n /**\n * Unique value for this item, used for selection matching with v-model.\n */\n value: {\n type: String,\n required: true,\n },\n\n /**\n * Accessible label for the button (aria-label).\n * Visible text comes from the default slot, not this prop.\n * Required for icon-only items.\n */\n label: {\n type: String,\n default: undefined,\n },\n\n /**\n * Disables this individual item.\n */\n disabled: {\n type: Boolean,\n default: false,\n },\n\n /**\n * Custom class for this item's label container.\n * Overrides the parent's labelClass when provided.\n */\n labelClass: {\n type: [String, Array, Object],\n default: undefined,\n },\n});\n\nconst emit = defineEmits([\n /**\n * Native button click event.\n * @event click\n * @type {PointerEvent | KeyboardEvent}\n */\n 'click',\n\n /**\n * Native button focus event.\n * @event focus\n * @type {FocusEvent}\n */\n 'focus',\n]);\n\nconst groupContext = inject(SEGMENTED_CONTROL_CONTEXT_KEY, { selected: '', disabled: false, size: SEGMENTED_CONTROL_SIZE_DEFAULT, labelClass: '' });\nconst selectValue = inject(SEGMENTED_CONTROL_SELECT_KEY, () => {});\nconst setFocus = inject(SEGMENTED_CONTROL_FOCUS_KEY, () => {});\n\nconst isSelected = computed(() => groupContext.selected === props.value);\nconst isDisabled = computed(() => groupContext.disabled || props.disabled);\n\nconst buttonSize = computed(() => groupContext.size);\n\nconst resolvedLabelClass = computed(() => {\n return ['d-segmented-control__item-label', props.labelClass ?? groupContext.labelClass].filter(Boolean);\n});\n\nfunction handleClick (event) {\n emit('click', event);\n if (isDisabled.value) return;\n selectValue(props.value);\n}\n\nfunction handleFocus (event) {\n emit('focus', event);\n setFocus(props.value);\n}\n</script>\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"segmented-control-item.cjs","names":["$attrs","$slots"],"sources":["../../../components/SegmentedControl/SegmentedControlItem.vue"],"sourcesContent":["<template>\n <dt-button\n class=\"d-segmented-control__item\"\n role=\"radio\"\n :aria-checked=\"String(isSelected)\"\n :tabindex=\"isSelected && !isDisabled ? '0' : '-1'\"\n :active=\"isSelected\"\n :disabled=\"isDisabled\"\n :aria-disabled=\"isDisabled ? 'true' : undefined\"\n :aria-label=\"label\"\n :label-class=\"resolvedLabelClass\"\n :data-value=\"value\"\n kind=\"muted\"\n importance=\"clear\"\n :size=\"buttonSize\"\n data-qa=\"dt-segmented-control-item\"\n v-bind=\"$attrs\"\n @click=\"handleClick\"\n @focus=\"handleFocus\"\n >\n <template\n v-if=\"$slots.startIcon\"\n #startIcon=\"{ iconSize }\"\n >\n <!-- @slot Icon displayed at the inline-start of the label. Provides { iconSize } scoped binding. -->\n <slot\n name=\"startIcon\"\n :icon-size=\"iconSize\"\n />\n </template>\n <template\n v-if=\"$slots.endIcon\"\n #endIcon=\"{ iconSize }\"\n >\n <!-- @slot Icon displayed at the inline-end of the label. Provides { iconSize } scoped binding. -->\n <slot\n name=\"endIcon\"\n :icon-size=\"iconSize\"\n />\n </template>\n <template\n v-if=\"$slots.leading\"\n #leading\n >\n <!-- @slot Content rendered before the label (e.g. badges, indicators). -->\n <slot name=\"leading\" />\n </template>\n <template\n v-if=\"$slots.trailing\"\n #trailing\n >\n <!-- @slot Content rendered after the label (e.g. badges, counts). -->\n <slot name=\"trailing\" />\n </template>\n <!-- @slot Label text content -->\n <slot />\n </dt-button>\n</template>\n\n<script setup>\nimport { computed, inject } from 'vue';\nimport { DtButton } from '@/components/Button';\nimport {\n SEGMENTED_CONTROL_CONTEXT_KEY,\n SEGMENTED_CONTROL_SELECT_KEY,\n SEGMENTED_CONTROL_FOCUS_KEY,\n SEGMENTED_CONTROL_SIZE_DEFAULT,\n} from './SegmentedControlConstants.js';\n\n/**\n * A choice within DtSegmentedControl. Additional attributes are forwarded to DtButton.\n * trailingClass customizes the trailing slot container and accepts a string, array or object.\n * @property {String|Array|Object} trailingClass attribute\n */\ndefineOptions({\n name: 'DtSegmentedControlItem',\n inheritAttrs: false,\n});\n\nconst props = defineProps({\n /**\n * Unique value for this item, used for selection matching with v-model.\n */\n value: {\n type: String,\n required: true,\n },\n\n /**\n * Accessible label for the button (aria-label).\n * Visible text comes from the default slot, not this prop.\n * Required for icon-only items.\n */\n label: {\n type: String,\n default: undefined,\n },\n\n /**\n * Disables this individual item.\n */\n disabled: {\n type: Boolean,\n default: false,\n },\n\n /**\n * Custom class for this item's label container.\n * Overrides the parent's labelClass when provided.\n */\n labelClass: {\n type: [String, Array, Object],\n default: undefined,\n },\n});\n\nconst emit = defineEmits([\n /**\n * Native button click event.\n * @event click\n * @type {PointerEvent | KeyboardEvent}\n */\n 'click',\n\n /**\n * Native button focus event.\n * @event focus\n * @type {FocusEvent}\n */\n 'focus',\n]);\n\nconst groupContext = inject(SEGMENTED_CONTROL_CONTEXT_KEY, { selected: '', disabled: false, size: SEGMENTED_CONTROL_SIZE_DEFAULT, labelClass: '' });\nconst selectValue = inject(SEGMENTED_CONTROL_SELECT_KEY, () => {});\nconst setFocus = inject(SEGMENTED_CONTROL_FOCUS_KEY, () => {});\n\nconst isSelected = computed(() => groupContext.selected === props.value);\nconst isDisabled = computed(() => groupContext.disabled || props.disabled);\n\nconst buttonSize = computed(() => groupContext.size);\n\nconst resolvedLabelClass = computed(() => {\n return ['d-segmented-control__item-label', props.labelClass ?? groupContext.labelClass].filter(Boolean);\n});\n\nfunction handleClick (event) {\n emit('click', event);\n if (isDisabled.value) return;\n selectValue(props.value);\n}\n\nfunction handleFocus (event) {\n emit('focus', event);\n setFocus(props.value);\n}\n</script>\n"],"mappings":"iiBA+EA,IAAM,EAAQ,EAqCR,EAAO,EAgBP,GAAA,EAAA,EAAA,QAAsB,EAAA,8BAA+B,CAAE,SAAU,GAAI,SAAU,GAAO,KAAA,IAAsC,WAAY,GAAI,CAAC,CAC7I,GAAA,EAAA,EAAA,QAAqB,EAAA,iCAAoC,GAAG,CAC5D,GAAA,EAAA,EAAA,QAAkB,EAAA,gCAAmC,GAAG,CAExD,GAAA,EAAA,EAAA,cAA4B,EAAa,WAAa,EAAM,MAAM,CAClE,GAAA,EAAA,EAAA,cAA4B,EAAa,UAAY,EAAM,SAAS,CAEpE,GAAA,EAAA,EAAA,cAA4B,EAAa,KAAK,CAE9C,GAAA,EAAA,EAAA,cACG,CAAC,kCAAmC,EAAM,YAAc,EAAa,WAAW,CAAC,OAAO,QAAQ,CACvG,CAEF,SAAS,EAAa,EAAO,CAC3B,EAAK,QAAS,EAAM,CAChB,GAAW,OACf,EAAY,EAAM,MAAM,CAG1B,SAAS,EAAa,EAAO,CAC3B,EAAK,QAAS,EAAM,CACpB,EAAS,EAAM,MAAM,+DAjGT,EAAA,QAAA,EAAA,EAAA,EAAA,YAAA,CAtDV,MAAM,4BACN,KAAK,QACJ,eAAc,OAAO,EAAA,MAAU,CAC/B,SAAU,EAAA,OAAU,CAAK,EAAA,MAAU,IAAA,KACnC,OAAQ,EAAA,MACR,SAAU,EAAA,MACV,gBAAe,EAAA,MAAU,OAAY,IAAA,GACrC,aAAY,EAAA,MACZ,cAAa,EAAA,MACb,aAAY,EAAA,MACb,KAAK,QACL,WAAW,QACV,KAAM,EAAA,MACP,UAAQ,6BACAA,EAAAA,OAAM,CACb,QAAO,EACP,QAAO,iDAqCA,EAAA,EAAA,EAAA,YAAA,EAAA,OAAA,UAAA,CAAA,CAAA,OAlCAC,EAAAA,OAAO,UAAA,MACZ,8BAMC,CANY,cAAQ,EAAA,EAAA,EAAA,YAMpB,EAAA,OAAA,YAAA,CADY,WAAQ,CAAA,CAAA,CAAA,iBAIhBA,EAAAA,OAAO,QAAA,MACZ,4BAMC,CANU,cAAQ,EAAA,EAAA,EAAA,YAMlB,EAAA,OAAA,UAAA,CADY,WAAQ,CAAA,CAAA,CAAA,iBAIhBA,EAAAA,OAAO,QAAA,MACZ,+BAGsB,EAAA,EAAA,EAAA,YAAA,EAAA,OAAA,UAAA,CAAA,CAAA,iBAGjBA,EAAAA,OAAO,SAAA,MACZ,gCAGuB,EAAA,EAAA,EAAA,YAAA,EAAA,OAAA,WAAA,CAAA,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"segmented-control-item.js","names":["$attrs","$slots"],"sources":["../../../components/SegmentedControl/SegmentedControlItem.vue"],"sourcesContent":["<template>\n <dt-button\n class=\"d-segmented-control__item\"\n role=\"radio\"\n :aria-checked=\"String(isSelected)\"\n :tabindex=\"isSelected && !isDisabled ? '0' : '-1'\"\n :active=\"isSelected\"\n :disabled=\"isDisabled\"\n :aria-disabled=\"isDisabled ? 'true' : undefined\"\n :aria-label=\"label\"\n :label-class=\"resolvedLabelClass\"\n :data-value=\"value\"\n kind=\"muted\"\n importance=\"clear\"\n :size=\"buttonSize\"\n data-qa=\"dt-segmented-control-item\"\n v-bind=\"$attrs\"\n @click=\"handleClick\"\n @focus=\"handleFocus\"\n >\n <template\n v-if=\"$slots.startIcon\"\n #startIcon=\"{ iconSize }\"\n >\n <!-- @slot Icon displayed at the inline-start of the label. Provides { iconSize } scoped binding. -->\n <slot\n name=\"startIcon\"\n :icon-size=\"iconSize\"\n />\n </template>\n <template\n v-if=\"$slots.endIcon\"\n #endIcon=\"{ iconSize }\"\n >\n <!-- @slot Icon displayed at the inline-end of the label. Provides { iconSize } scoped binding. -->\n <slot\n name=\"endIcon\"\n :icon-size=\"iconSize\"\n />\n </template>\n <template\n v-if=\"$slots.leading\"\n #leading\n >\n <!-- @slot Content rendered before the label (e.g. badges, indicators). -->\n <slot name=\"leading\" />\n </template>\n <template\n v-if=\"$slots.trailing\"\n #trailing\n >\n <!-- @slot Content rendered after the label (e.g. badges, counts). -->\n <slot name=\"trailing\" />\n </template>\n <!-- @slot Label text content -->\n <slot />\n </dt-button>\n</template>\n\n<script setup>\nimport { computed, inject } from 'vue';\nimport { DtButton } from '@/components/Button';\nimport {\n SEGMENTED_CONTROL_CONTEXT_KEY,\n SEGMENTED_CONTROL_SELECT_KEY,\n SEGMENTED_CONTROL_FOCUS_KEY,\n SEGMENTED_CONTROL_SIZE_DEFAULT,\n} from './SegmentedControlConstants.js';\n\ndefineOptions({\n name: 'DtSegmentedControlItem',\n inheritAttrs: false,\n});\n\nconst props = defineProps({\n /**\n * Unique value for this item, used for selection matching with v-model.\n */\n value: {\n type: String,\n required: true,\n },\n\n /**\n * Accessible label for the button (aria-label).\n * Visible text comes from the default slot, not this prop.\n * Required for icon-only items.\n */\n label: {\n type: String,\n default: undefined,\n },\n\n /**\n * Disables this individual item.\n */\n disabled: {\n type: Boolean,\n default: false,\n },\n\n /**\n * Custom class for this item's label container.\n * Overrides the parent's labelClass when provided.\n */\n labelClass: {\n type: [String, Array, Object],\n default: undefined,\n },\n});\n\nconst emit = defineEmits([\n /**\n * Native button click event.\n * @event click\n * @type {PointerEvent | KeyboardEvent}\n */\n 'click',\n\n /**\n * Native button focus event.\n * @event focus\n * @type {FocusEvent}\n */\n 'focus',\n]);\n\nconst groupContext = inject(SEGMENTED_CONTROL_CONTEXT_KEY, { selected: '', disabled: false, size: SEGMENTED_CONTROL_SIZE_DEFAULT, labelClass: '' });\nconst selectValue = inject(SEGMENTED_CONTROL_SELECT_KEY, () => {});\nconst setFocus = inject(SEGMENTED_CONTROL_FOCUS_KEY, () => {});\n\nconst isSelected = computed(() => groupContext.selected === props.value);\nconst isDisabled = computed(() => groupContext.disabled || props.disabled);\n\nconst buttonSize = computed(() => groupContext.size);\n\nconst resolvedLabelClass = computed(() => {\n return ['d-segmented-control__item-label', props.labelClass ?? groupContext.labelClass].filter(Boolean);\n});\n\nfunction handleClick (event) {\n emit('click', event);\n if (isDisabled.value) return;\n selectValue(props.value);\n}\n\nfunction handleFocus (event) {\n emit('focus', event);\n setFocus(props.value);\n}\n</script>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"segmented-control-item.js","names":["$attrs","$slots"],"sources":["../../../components/SegmentedControl/SegmentedControlItem.vue"],"sourcesContent":["<template>\n <dt-button\n class=\"d-segmented-control__item\"\n role=\"radio\"\n :aria-checked=\"String(isSelected)\"\n :tabindex=\"isSelected && !isDisabled ? '0' : '-1'\"\n :active=\"isSelected\"\n :disabled=\"isDisabled\"\n :aria-disabled=\"isDisabled ? 'true' : undefined\"\n :aria-label=\"label\"\n :label-class=\"resolvedLabelClass\"\n :data-value=\"value\"\n kind=\"muted\"\n importance=\"clear\"\n :size=\"buttonSize\"\n data-qa=\"dt-segmented-control-item\"\n v-bind=\"$attrs\"\n @click=\"handleClick\"\n @focus=\"handleFocus\"\n >\n <template\n v-if=\"$slots.startIcon\"\n #startIcon=\"{ iconSize }\"\n >\n <!-- @slot Icon displayed at the inline-start of the label. Provides { iconSize } scoped binding. -->\n <slot\n name=\"startIcon\"\n :icon-size=\"iconSize\"\n />\n </template>\n <template\n v-if=\"$slots.endIcon\"\n #endIcon=\"{ iconSize }\"\n >\n <!-- @slot Icon displayed at the inline-end of the label. Provides { iconSize } scoped binding. -->\n <slot\n name=\"endIcon\"\n :icon-size=\"iconSize\"\n />\n </template>\n <template\n v-if=\"$slots.leading\"\n #leading\n >\n <!-- @slot Content rendered before the label (e.g. badges, indicators). -->\n <slot name=\"leading\" />\n </template>\n <template\n v-if=\"$slots.trailing\"\n #trailing\n >\n <!-- @slot Content rendered after the label (e.g. badges, counts). -->\n <slot name=\"trailing\" />\n </template>\n <!-- @slot Label text content -->\n <slot />\n </dt-button>\n</template>\n\n<script setup>\nimport { computed, inject } from 'vue';\nimport { DtButton } from '@/components/Button';\nimport {\n SEGMENTED_CONTROL_CONTEXT_KEY,\n SEGMENTED_CONTROL_SELECT_KEY,\n SEGMENTED_CONTROL_FOCUS_KEY,\n SEGMENTED_CONTROL_SIZE_DEFAULT,\n} from './SegmentedControlConstants.js';\n\n/**\n * A choice within DtSegmentedControl. Additional attributes are forwarded to DtButton.\n * trailingClass customizes the trailing slot container and accepts a string, array or object.\n * @property {String|Array|Object} trailingClass attribute\n */\ndefineOptions({\n name: 'DtSegmentedControlItem',\n inheritAttrs: false,\n});\n\nconst props = defineProps({\n /**\n * Unique value for this item, used for selection matching with v-model.\n */\n value: {\n type: String,\n required: true,\n },\n\n /**\n * Accessible label for the button (aria-label).\n * Visible text comes from the default slot, not this prop.\n * Required for icon-only items.\n */\n label: {\n type: String,\n default: undefined,\n },\n\n /**\n * Disables this individual item.\n */\n disabled: {\n type: Boolean,\n default: false,\n },\n\n /**\n * Custom class for this item's label container.\n * Overrides the parent's labelClass when provided.\n */\n labelClass: {\n type: [String, Array, Object],\n default: undefined,\n },\n});\n\nconst emit = defineEmits([\n /**\n * Native button click event.\n * @event click\n * @type {PointerEvent | KeyboardEvent}\n */\n 'click',\n\n /**\n * Native button focus event.\n * @event focus\n * @type {FocusEvent}\n */\n 'focus',\n]);\n\nconst groupContext = inject(SEGMENTED_CONTROL_CONTEXT_KEY, { selected: '', disabled: false, size: SEGMENTED_CONTROL_SIZE_DEFAULT, labelClass: '' });\nconst selectValue = inject(SEGMENTED_CONTROL_SELECT_KEY, () => {});\nconst setFocus = inject(SEGMENTED_CONTROL_FOCUS_KEY, () => {});\n\nconst isSelected = computed(() => groupContext.selected === props.value);\nconst isDisabled = computed(() => groupContext.disabled || props.disabled);\n\nconst buttonSize = computed(() => groupContext.size);\n\nconst resolvedLabelClass = computed(() => {\n return ['d-segmented-control__item-label', props.labelClass ?? groupContext.labelClass].filter(Boolean);\n});\n\nfunction handleClick (event) {\n emit('click', event);\n if (isDisabled.value) return;\n selectValue(props.value);\n}\n\nfunction handleFocus (event) {\n emit('focus', event);\n setFocus(props.value);\n}\n</script>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA+EA,IAAM,IAAQ,GAqCR,IAAO,GAgBP,IAAe,EAAO,GAA+B;GAAE,UAAU;GAAI,UAAU;GAAO,MAAA;GAAsC,YAAY;GAAI,CAAC,EAC7I,IAAc,EAAO,SAAoC,GAAG,EAC5D,IAAW,EAAO,SAAmC,GAAG,EAExD,IAAa,QAAe,EAAa,aAAa,EAAM,MAAM,EAClE,IAAa,QAAe,EAAa,YAAY,EAAM,SAAS,EAEpE,IAAa,QAAe,EAAa,KAAK,EAE9C,IAAqB,QAClB,CAAC,mCAAmC,EAAM,cAAc,EAAa,WAAW,CAAC,OAAO,QAAQ,CACvG;EAEF,SAAS,EAAa,GAAO;AAC3B,KAAK,SAAS,EAAM,EAChB,GAAW,SACf,EAAY,EAAM,MAAM;;EAG1B,SAAS,EAAa,GAAO;AAE3B,GADA,EAAK,SAAS,EAAM,EACpB,EAAS,EAAM,MAAM;;yBAxJrB,EAuDY,EAAA,EAAA,EAvDZ,EAuDY;GAtDV,OAAM;GACN,MAAK;GACJ,gBAAc,OAAO,EAAA,MAAU;GAC/B,UAAU,EAAA,SAAU,CAAK,EAAA,QAAU,MAAA;GACnC,QAAQ,EAAA;GACR,UAAU,EAAA;GACV,iBAAe,EAAA,QAAU,SAAY,KAAA;GACrC,cAAY,EAAA;GACZ,eAAa,EAAA;GACb,cAAY,EAAA;GACb,MAAK;GACL,YAAW;GACV,MAAM,EAAA;GACP,WAAQ;KACAA,EAAAA,QAAM;GACb,SAAO;GACP,SAAO;;oBAqCA,CAAR,EAAQ,EAAA,QAAA,UAAA,CAAA,CAAA;;;GAlCAC,EAAAA,OAAO,YAAA;UACZ;WAMC,EANY,kBAAQ,CAGtB,EAGE,EAAA,QAAA,aAAA,EADY,aAAQ,CAAA,CAAA,CAAA;;;GAIhBA,EAAAA,OAAO,UAAA;UACZ;WAMC,EANU,kBAAQ,CAGpB,EAGE,EAAA,QAAA,WAAA,EADY,aAAQ,CAAA,CAAA,CAAA;;;GAIhBA,EAAAA,OAAO,UAAA;UACZ;gBAGsB,CAAvB,EAAuB,EAAA,QAAA,UAAA,CAAA,CAAA;;;GAGjBA,EAAAA,OAAO,WAAA;UACZ;gBAGuB,CAAxB,EAAwB,EAAA,QAAA,WAAA,CAAA,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"text.cjs","names":[],"sources":["../../../components/Text/Text.vue"],"sourcesContent":["<template>\n <component\n :is=\"as\"\n data-qa=\"dt-text\"\n :class=\"textClasses\"\n :style=\"textStyles\"\n >\n <!-- @slot Default slot for text content -->\n <slot />\n </component>\n</template>\n\n<script>\nimport {\n TEXT_KIND_MODIFIERS,\n TEXT_VARIANT_MODIFIERS,\n TEXT_SIZE_MODIFIERS,\n TEXT_SIZE_MAP,\n TEXT_HEADLINE_ONLY_SIZES,\n TEXT_FONT_SIZE_MODIFIERS,\n TEXT_FAMILY_MODIFIERS,\n TEXT_ITALIC_CLASS,\n TEXT_ALIGN_MODIFIERS,\n TEXT_TONE_MODIFIERS,\n TEXT_NUMERIC_CLASS,\n TEXT_TRUNCATE_CLASS,\n TEXT_LINE_CLAMP_CLASS,\n TEXT_WRAP_MODIFIERS,\n TEXT_BOX_TRIM_MODIFIERS,\n TEXT_STRENGTH_MODIFIERS,\n TEXT_DENSITY_MODIFIERS,\n} from './TextConstants';\n\nconst DEFAULT_SIZE = '300';\nconst SEMANTIC_HEADING_ELEMENTS = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'];\n\n// Module-level flag to emit info only once per session\nlet hasEmittedHeadlineSemanticInfo = false;\n\n// Exported for testing purposes only\nexport const resetHeadlineSemanticInfoFlag = () => {\n hasEmittedHeadlineSemanticInfo = false;\n};\n\n/**\n * Dialtone text primitive that applies typography tokens based on semantic props.\n * @see https://dialtone.dialpad.com/components/text.html\n */\nexport default {\n name: 'DtText',\n\n props: {\n /**\n * HTML tag or component used for rendering.\n * @values span, p, h1, h2, h3, h4, h5, h6, label, div, component\n */\n as: {\n type: String,\n default: 'span',\n },\n\n /**\n * Typography kind mapping to headline/body/label/code token sets.\n * @values headline, body, label, code\n * @deprecated Use variant instead\n */\n kind: {\n type: String,\n default: null,\n validator: (value) => {\n return (\n value === null ||\n Object.prototype.hasOwnProperty.call(TEXT_KIND_MODIFIERS, value)\n );\n },\n },\n\n /**\n * Typography variant mapping to a complete token-backed composition.\n * @values headline-3xl, headline-2xl, headline-xl, headline-lg, headline-md, headline-sm, headline-xs, body-lg, body-md, body-sm, body-xs, label-lg, label-md, label-sm, label-xs, code-lg, code-md, code-sm, code-xs\n */\n variant: {\n type: String,\n default: null,\n validator: (value) => {\n return (\n value === null ||\n Object.prototype.hasOwnProperty.call(TEXT_VARIANT_MODIFIERS, value)\n );\n },\n },\n\n /**\n * Raw font-size token. Must be paired with `variant` for overrides or legacy `kind` for composition size.\n * @values 50, 75, 100, 125, 150, 200, 250, 300, 350, 400, 450, 500, 550, 600, 650, 700, 750, 800\n */\n size: {\n type: [String, Number],\n default: null,\n },\n\n /**\n * Overrides font-family. By default, no font-family class is emitted and text inherits naturally.\n * @values inherit, custom, sans, mono, expressive\n */\n family: {\n type: String,\n default: null,\n validator: (value) => {\n return (\n value === null ||\n Object.prototype.hasOwnProperty.call(TEXT_FAMILY_MODIFIERS, value)\n );\n },\n },\n\n /**\n * Applies italic font style when true.\n */\n italic: {\n type: Boolean,\n default: false,\n },\n\n /**\n * Semantic foreground color.\n * @values primary, secondary, tertiary, muted, disabled, placeholder, critical, critical-strong, positive, positive-strong, warning, info, info-strong, neutral-black, neutral-white\n */\n tone: {\n type: String,\n default: null,\n validator: (value) => {\n return (\n value === null ||\n Object.prototype.hasOwnProperty.call(TEXT_TONE_MODIFIERS, value)\n );\n },\n },\n\n /**\n * Logical text alignment. Requires block/inline-block context.\n * @values start, center, end, justify\n */\n align: {\n type: String,\n default: null,\n validator: (value) => {\n return (\n value === null ||\n Object.prototype.hasOwnProperty.call(TEXT_ALIGN_MODIFIERS, value)\n );\n },\n },\n\n /**\n * Enables single-line truncation (i.e. ellipsis) when true; requires block/inline-block context.\n */\n truncate: {\n type: Boolean,\n default: false,\n },\n\n /**\n * Applies multi-line truncation (i.e. clamp) when greater than zero; requires block/inline-block context.\n */\n maxLines: {\n type: Number,\n default: null,\n validator: (value) => {\n return value === null || (Number.isInteger(value) && value > 0);\n },\n },\n\n /**\n * Renders numeric content with tabular figures.\n */\n numeric: {\n type: Boolean,\n default: false,\n },\n\n /**\n * Controls text wrapping behavior.\n * @values wrap, nowrap, balance, pretty\n */\n wrap: {\n type: String,\n default: null,\n validator: (value) => {\n return (\n value === null ||\n Object.prototype.hasOwnProperty.call(TEXT_WRAP_MODIFIERS, value)\n );\n },\n },\n\n /**\n * Controls text-box-trim (leading space above/below text). Useful for tight component layouts.\n * @values start, end, both\n */\n textBoxTrim: {\n type: String,\n default: null,\n validator: (value) => {\n return (\n value === null ||\n Object.prototype.hasOwnProperty.call(TEXT_BOX_TRIM_MODIFIERS, value)\n );\n },\n },\n\n /**\n * Overrides font-weight. Applies to any kind/size combination.\n * @values bold, semibold, medium, normal\n */\n strength: {\n type: String,\n default: null,\n validator: (value) => {\n return (\n value === null ||\n Object.prototype.hasOwnProperty.call(TEXT_STRENGTH_MODIFIERS, value)\n );\n },\n },\n\n /**\n * Overrides line-height. Applies to any kind/size combination.\n * @values 100, 200, 300, 400, 500, 600\n */\n density: {\n type: [String, Number],\n default: null,\n validator: (value) => {\n return (\n value === null ||\n Object.prototype.hasOwnProperty.call(TEXT_DENSITY_MODIFIERS, value)\n );\n },\n },\n },\n\n computed: {\n textClasses() {\n const classes = ['d-text'];\n const variantClass = this.getVariantClass();\n if (variantClass) {\n classes.push(variantClass);\n }\n\n const fontSizeClass = this.getFontSizeClass();\n if (fontSizeClass) {\n classes.push(fontSizeClass);\n }\n\n const familyClass = this.getFamilyClass();\n if (familyClass) {\n classes.push(familyClass);\n }\n\n if (this.italic) {\n classes.push(TEXT_ITALIC_CLASS);\n }\n\n const alignClass = this.getAlignClass();\n if (alignClass) {\n classes.push(alignClass);\n }\n\n const toneClass = this.getToneClass();\n if (toneClass) {\n classes.push(toneClass);\n }\n\n if (this.truncate) {\n classes.push(TEXT_TRUNCATE_CLASS);\n }\n\n if (this.numeric) {\n classes.push(TEXT_NUMERIC_CLASS);\n }\n\n if (this.maxLines) {\n classes.push(TEXT_LINE_CLAMP_CLASS);\n }\n\n const wrapClass = this.getWrapClass();\n if (wrapClass) {\n classes.push(wrapClass);\n }\n\n const textBoxTrimClass = this.getTextBoxTrimClass();\n if (textBoxTrimClass) {\n classes.push(textBoxTrimClass);\n }\n\n const strengthClass = this.getStrengthClass();\n if (strengthClass) {\n classes.push(strengthClass);\n }\n\n const densityClass = this.getDensityClass();\n if (densityClass) {\n classes.push(densityClass);\n }\n\n return classes;\n },\n\n textStyles() {\n if (!this.maxLines) {\n return undefined;\n }\n\n return {\n '--dt-text-line-clamp': this.maxLines,\n };\n },\n },\n\n mounted() {\n // Emit info once per session when headline is used without semantic heading element\n if (\n !hasEmittedHeadlineSemanticInfo &&\n this.usesHeadlineVisualStyle() &&\n !SEMANTIC_HEADING_ELEMENTS.includes(this.as)\n ) {\n console.info(\n '[DtText] A headline text style is used without a semantic heading element. ' +\n 'Consider using as=\"h1|h2|h3|h4|h5|h6\" for better accessibility.',\n );\n hasEmittedHeadlineSemanticInfo = true;\n }\n },\n\n methods: {\n usesHeadlineVisualStyle() {\n if (this.variant) {\n return this.variant.startsWith('headline-');\n }\n\n return this.kind === 'headline';\n },\n\n usesLegacyKindSize() {\n return Boolean(this.kind && !this.variant);\n },\n\n getVariantClass() {\n if (this.variant) {\n return this.getModifierClass(\n this.variant,\n TEXT_VARIANT_MODIFIERS,\n 'variant',\n );\n }\n\n if (!this.kind) {\n return null;\n }\n\n if (\n !Object.prototype.hasOwnProperty.call(TEXT_KIND_MODIFIERS, this.kind)\n ) {\n console.warn(`[DtText] Unsupported kind \"${this.kind}\".`);\n return null;\n }\n\n const allowedSizes = TEXT_SIZE_MODIFIERS[this.kind] || [];\n const rawSize = this.size != null ? String(this.size) : null;\n const requestedSize = rawSize || DEFAULT_SIZE;\n let resolvedSize = requestedSize;\n\n if (!allowedSizes.includes(requestedSize)) {\n // Headline-only sizes (3xl, 2xl, xl, 500, 600, 700) throw an error when used with incompatible kinds\n if (TEXT_HEADLINE_ONLY_SIZES.includes(requestedSize)) {\n throw new Error(\n `[DtText] size=\"${requestedSize}\" is only valid for kind=\"headline\". ` +\n `Cannot use with kind=\"${this.kind}\".`,\n );\n }\n\n // Universal sizes fall back gracefully with a warning\n const fallbackSize = allowedSizes.includes(DEFAULT_SIZE)\n ? DEFAULT_SIZE\n : allowedSizes[0];\n if (fallbackSize) {\n resolvedSize = fallbackSize;\n }\n console.warn(\n `[DtText] size=\"${requestedSize}\" is not valid for kind=\"${this.kind}\". Using \"${resolvedSize}\" instead.`,\n );\n }\n\n if (!resolvedSize) {\n return null;\n }\n\n // Map numeric sizes to t-shirt CSS class suffix\n const cssSuffix = TEXT_SIZE_MAP[resolvedSize] || resolvedSize;\n return `${TEXT_KIND_MODIFIERS[this.kind]}--${cssSuffix}`;\n },\n\n getFontSizeClass() {\n if (this.size === null || this.size === undefined) {\n return null;\n }\n\n if (!this.variant && !this.kind) {\n console.warn(\n '[DtText] size must be paired with variant or legacy kind. ' +\n 'Prefer variant for typography composition; use size only as a variant override.',\n );\n return null;\n }\n\n if (this.usesLegacyKindSize()) {\n return null;\n }\n\n const size = String(this.size);\n const className = TEXT_FONT_SIZE_MODIFIERS[size];\n if (className) {\n return className;\n }\n\n console.warn(\n `[DtText] Unsupported size \"${size}\". Use a numeric font-size token.`,\n );\n return null;\n },\n\n getModifierClass(value, modifiers, propName) {\n if (value === null || value === undefined) {\n return null;\n }\n\n const className = modifiers[value];\n if (!className) {\n console.warn(`[DtText] Unsupported ${propName} \"${value}\".`);\n return null;\n }\n\n return className;\n },\n\n getAlignClass() {\n return this.getModifierClass(this.align, TEXT_ALIGN_MODIFIERS, 'align');\n },\n\n getToneClass() {\n return this.getModifierClass(this.tone, TEXT_TONE_MODIFIERS, 'tone');\n },\n\n getWrapClass() {\n return this.getModifierClass(this.wrap, TEXT_WRAP_MODIFIERS, 'wrap');\n },\n\n getTextBoxTrimClass() {\n return this.getModifierClass(\n this.textBoxTrim,\n TEXT_BOX_TRIM_MODIFIERS,\n 'textBoxTrim',\n );\n },\n\n getStrengthClass() {\n return this.getModifierClass(\n this.strength,\n TEXT_STRENGTH_MODIFIERS,\n 'strength',\n );\n },\n\n getDensityClass() {\n return this.getModifierClass(\n this.density,\n TEXT_DENSITY_MODIFIERS,\n 'density',\n );\n },\n\n getFamilyClass() {\n return this.getModifierClass(\n this.family,\n TEXT_FAMILY_MODIFIERS,\n 'family',\n );\n },\n },\n};\n</script>\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"text.cjs","names":[],"sources":["../../../components/Text/Text.vue"],"sourcesContent":["<template>\n <component\n :is=\"as\"\n data-qa=\"dt-text\"\n :class=\"textClasses\"\n :style=\"textStyles\"\n >\n <!-- @slot Default slot for text content -->\n <slot />\n </component>\n</template>\n\n<script>\nimport {\n TEXT_KIND_MODIFIERS,\n TEXT_VARIANT_MODIFIERS,\n TEXT_SIZE_MODIFIERS,\n TEXT_SIZE_MAP,\n TEXT_HEADLINE_ONLY_SIZES,\n TEXT_FONT_SIZE_MODIFIERS,\n TEXT_FAMILY_MODIFIERS,\n TEXT_ITALIC_CLASS,\n TEXT_ALIGN_MODIFIERS,\n TEXT_TONE_MODIFIERS,\n TEXT_NUMERIC_CLASS,\n TEXT_TRUNCATE_CLASS,\n TEXT_LINE_CLAMP_CLASS,\n TEXT_WRAP_MODIFIERS,\n TEXT_BOX_TRIM_MODIFIERS,\n TEXT_STRENGTH_MODIFIERS,\n TEXT_DENSITY_MODIFIERS,\n} from './TextConstants';\n\nconst DEFAULT_SIZE = '300';\nconst SEMANTIC_HEADING_ELEMENTS = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'];\n\n// Module-level flag to emit info only once per session\nlet hasEmittedHeadlineSemanticInfo = false;\n\n// Exported for testing purposes only\nexport const resetHeadlineSemanticInfoFlag = () => {\n hasEmittedHeadlineSemanticInfo = false;\n};\n\n/**\n * Dialtone text primitive that applies typography tokens based on semantic props.\n * @see https://dialtone.dialpad.com/components/text.html\n */\nexport default {\n name: 'DtText',\n\n props: {\n /**\n * HTML tag or component used for rendering.\n * @values span, p, strong, h1, h2, h3, h4, h5, h6, label, div, component\n */\n as: {\n type: String,\n default: 'span',\n },\n\n /**\n * Typography kind mapping to headline/body/label/code token sets.\n * @values headline, body, label, code\n * @deprecated Use variant instead\n */\n kind: {\n type: String,\n default: null,\n validator: (value) => {\n return (\n value === null ||\n Object.prototype.hasOwnProperty.call(TEXT_KIND_MODIFIERS, value)\n );\n },\n },\n\n /**\n * Typography variant mapping to a complete token-backed composition.\n * @values headline-3xl, headline-2xl, headline-xl, headline-lg, headline-md, headline-sm, headline-xs, body-lg, body-md, body-sm, body-xs, label-lg, label-md, label-sm, label-xs, code-lg, code-md, code-sm, code-xs\n */\n variant: {\n type: String,\n default: null,\n validator: (value) => {\n return (\n value === null ||\n Object.prototype.hasOwnProperty.call(TEXT_VARIANT_MODIFIERS, value)\n );\n },\n },\n\n /**\n * Raw font-size token. Must be paired with `variant` for overrides or legacy `kind` for composition size.\n * @values 50, 75, 100, 125, 150, 200, 250, 300, 350, 400, 450, 500, 550, 600, 650, 700, 750, 800\n */\n size: {\n type: [String, Number],\n default: null,\n },\n\n /**\n * Overrides font-family. By default, no font-family class is emitted and text inherits naturally.\n * @values inherit, custom, sans, mono, expressive\n */\n family: {\n type: String,\n default: null,\n validator: (value) => {\n return (\n value === null ||\n Object.prototype.hasOwnProperty.call(TEXT_FAMILY_MODIFIERS, value)\n );\n },\n },\n\n /**\n * Applies italic font style when true.\n */\n italic: {\n type: Boolean,\n default: false,\n },\n\n /**\n * Semantic foreground color.\n * @values primary, secondary, tertiary, muted, disabled, placeholder, critical, critical-strong, positive, positive-strong, warning, info, info-strong, neutral-black, neutral-white\n */\n tone: {\n type: String,\n default: null,\n validator: (value) => {\n return (\n value === null ||\n Object.prototype.hasOwnProperty.call(TEXT_TONE_MODIFIERS, value)\n );\n },\n },\n\n /**\n * Logical text alignment. Requires block/inline-block context.\n * @values start, center, end, justify\n */\n align: {\n type: String,\n default: null,\n validator: (value) => {\n return (\n value === null ||\n Object.prototype.hasOwnProperty.call(TEXT_ALIGN_MODIFIERS, value)\n );\n },\n },\n\n /**\n * Enables single-line truncation (i.e. ellipsis) when true; requires block/inline-block context.\n */\n truncate: {\n type: Boolean,\n default: false,\n },\n\n /**\n * Applies multi-line truncation (i.e. clamp) when greater than zero; requires block/inline-block context.\n */\n maxLines: {\n type: Number,\n default: null,\n validator: (value) => {\n return value === null || (Number.isInteger(value) && value > 0);\n },\n },\n\n /**\n * Renders numeric content with tabular figures.\n */\n numeric: {\n type: Boolean,\n default: false,\n },\n\n /**\n * Controls text wrapping behavior.\n * @values wrap, nowrap, balance, pretty\n */\n wrap: {\n type: String,\n default: null,\n validator: (value) => {\n return (\n value === null ||\n Object.prototype.hasOwnProperty.call(TEXT_WRAP_MODIFIERS, value)\n );\n },\n },\n\n /**\n * Controls text-box-trim (leading space above/below text). Useful for tight component layouts.\n * @values start, end, both\n */\n textBoxTrim: {\n type: String,\n default: null,\n validator: (value) => {\n return (\n value === null ||\n Object.prototype.hasOwnProperty.call(TEXT_BOX_TRIM_MODIFIERS, value)\n );\n },\n },\n\n /**\n * Overrides font-weight. Applies to any kind/size combination.\n * @values bold, semibold, medium, normal\n */\n strength: {\n type: String,\n default: null,\n validator: (value) => {\n return (\n value === null ||\n Object.prototype.hasOwnProperty.call(TEXT_STRENGTH_MODIFIERS, value)\n );\n },\n },\n\n /**\n * Overrides line-height. Applies to any kind/size combination.\n * @values 100, 200, 300, 400, 500, 600\n */\n density: {\n type: [String, Number],\n default: null,\n validator: (value) => {\n return (\n value === null ||\n Object.prototype.hasOwnProperty.call(TEXT_DENSITY_MODIFIERS, value)\n );\n },\n },\n },\n\n computed: {\n textClasses() {\n const classes = ['d-text'];\n const variantClass = this.getVariantClass();\n if (variantClass) {\n classes.push(variantClass);\n }\n\n const fontSizeClass = this.getFontSizeClass();\n if (fontSizeClass) {\n classes.push(fontSizeClass);\n }\n\n const familyClass = this.getFamilyClass();\n if (familyClass) {\n classes.push(familyClass);\n }\n\n if (this.italic) {\n classes.push(TEXT_ITALIC_CLASS);\n }\n\n const alignClass = this.getAlignClass();\n if (alignClass) {\n classes.push(alignClass);\n }\n\n const toneClass = this.getToneClass();\n if (toneClass) {\n classes.push(toneClass);\n }\n\n if (this.truncate) {\n classes.push(TEXT_TRUNCATE_CLASS);\n }\n\n if (this.numeric) {\n classes.push(TEXT_NUMERIC_CLASS);\n }\n\n if (this.maxLines) {\n classes.push(TEXT_LINE_CLAMP_CLASS);\n }\n\n const wrapClass = this.getWrapClass();\n if (wrapClass) {\n classes.push(wrapClass);\n }\n\n const textBoxTrimClass = this.getTextBoxTrimClass();\n if (textBoxTrimClass) {\n classes.push(textBoxTrimClass);\n }\n\n const strengthClass = this.getStrengthClass();\n if (strengthClass) {\n classes.push(strengthClass);\n }\n\n const densityClass = this.getDensityClass();\n if (densityClass) {\n classes.push(densityClass);\n }\n\n return classes;\n },\n\n textStyles() {\n if (!this.maxLines) {\n return undefined;\n }\n\n return {\n '--dt-text-line-clamp': this.maxLines,\n };\n },\n },\n\n mounted() {\n // Emit info once per session when headline is used without semantic heading element\n if (\n !hasEmittedHeadlineSemanticInfo &&\n this.usesHeadlineVisualStyle() &&\n !SEMANTIC_HEADING_ELEMENTS.includes(this.as)\n ) {\n console.info(\n '[DtText] A headline text style is used without a semantic heading element. ' +\n 'Consider using as=\"h1|h2|h3|h4|h5|h6\" for better accessibility.',\n );\n hasEmittedHeadlineSemanticInfo = true;\n }\n },\n\n methods: {\n usesHeadlineVisualStyle() {\n if (this.variant) {\n return this.variant.startsWith('headline-');\n }\n\n return this.kind === 'headline';\n },\n\n usesLegacyKindSize() {\n return Boolean(this.kind && !this.variant);\n },\n\n getVariantClass() {\n if (this.variant) {\n return this.getModifierClass(\n this.variant,\n TEXT_VARIANT_MODIFIERS,\n 'variant',\n );\n }\n\n if (!this.kind) {\n return null;\n }\n\n if (\n !Object.prototype.hasOwnProperty.call(TEXT_KIND_MODIFIERS, this.kind)\n ) {\n console.warn(`[DtText] Unsupported kind \"${this.kind}\".`);\n return null;\n }\n\n const allowedSizes = TEXT_SIZE_MODIFIERS[this.kind] || [];\n const rawSize = this.size != null ? String(this.size) : null;\n const requestedSize = rawSize || DEFAULT_SIZE;\n let resolvedSize = requestedSize;\n\n if (!allowedSizes.includes(requestedSize)) {\n // Headline-only sizes (3xl, 2xl, xl, 500, 600, 700) throw an error when used with incompatible kinds\n if (TEXT_HEADLINE_ONLY_SIZES.includes(requestedSize)) {\n throw new Error(\n `[DtText] size=\"${requestedSize}\" is only valid for kind=\"headline\". ` +\n `Cannot use with kind=\"${this.kind}\".`,\n );\n }\n\n // Universal sizes fall back gracefully with a warning\n const fallbackSize = allowedSizes.includes(DEFAULT_SIZE)\n ? DEFAULT_SIZE\n : allowedSizes[0];\n if (fallbackSize) {\n resolvedSize = fallbackSize;\n }\n console.warn(\n `[DtText] size=\"${requestedSize}\" is not valid for kind=\"${this.kind}\". Using \"${resolvedSize}\" instead.`,\n );\n }\n\n if (!resolvedSize) {\n return null;\n }\n\n // Map numeric sizes to t-shirt CSS class suffix\n const cssSuffix = TEXT_SIZE_MAP[resolvedSize] || resolvedSize;\n return `${TEXT_KIND_MODIFIERS[this.kind]}--${cssSuffix}`;\n },\n\n getFontSizeClass() {\n if (this.size === null || this.size === undefined) {\n return null;\n }\n\n if (!this.variant && !this.kind) {\n console.warn(\n '[DtText] size must be paired with variant or legacy kind. ' +\n 'Prefer variant for typography composition; use size only as a variant override.',\n );\n return null;\n }\n\n if (this.usesLegacyKindSize()) {\n return null;\n }\n\n const size = String(this.size);\n const className = TEXT_FONT_SIZE_MODIFIERS[size];\n if (className) {\n return className;\n }\n\n console.warn(\n `[DtText] Unsupported size \"${size}\". Use a numeric font-size token.`,\n );\n return null;\n },\n\n getModifierClass(value, modifiers, propName) {\n if (value === null || value === undefined) {\n return null;\n }\n\n const className = modifiers[value];\n if (!className) {\n console.warn(`[DtText] Unsupported ${propName} \"${value}\".`);\n return null;\n }\n\n return className;\n },\n\n getAlignClass() {\n return this.getModifierClass(this.align, TEXT_ALIGN_MODIFIERS, 'align');\n },\n\n getToneClass() {\n return this.getModifierClass(this.tone, TEXT_TONE_MODIFIERS, 'tone');\n },\n\n getWrapClass() {\n return this.getModifierClass(this.wrap, TEXT_WRAP_MODIFIERS, 'wrap');\n },\n\n getTextBoxTrimClass() {\n return this.getModifierClass(\n this.textBoxTrim,\n TEXT_BOX_TRIM_MODIFIERS,\n 'textBoxTrim',\n );\n },\n\n getStrengthClass() {\n return this.getModifierClass(\n this.strength,\n TEXT_STRENGTH_MODIFIERS,\n 'strength',\n );\n },\n\n getDensityClass() {\n return this.getModifierClass(\n this.density,\n TEXT_DENSITY_MODIFIERS,\n 'density',\n );\n },\n\n getFamilyClass() {\n return this.getModifierClass(\n this.family,\n TEXT_FAMILY_MODIFIERS,\n 'family',\n );\n },\n },\n};\n</script>\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"text.js","names":[],"sources":["../../../components/Text/Text.vue"],"sourcesContent":["<template>\n <component\n :is=\"as\"\n data-qa=\"dt-text\"\n :class=\"textClasses\"\n :style=\"textStyles\"\n >\n <!-- @slot Default slot for text content -->\n <slot />\n </component>\n</template>\n\n<script>\nimport {\n TEXT_KIND_MODIFIERS,\n TEXT_VARIANT_MODIFIERS,\n TEXT_SIZE_MODIFIERS,\n TEXT_SIZE_MAP,\n TEXT_HEADLINE_ONLY_SIZES,\n TEXT_FONT_SIZE_MODIFIERS,\n TEXT_FAMILY_MODIFIERS,\n TEXT_ITALIC_CLASS,\n TEXT_ALIGN_MODIFIERS,\n TEXT_TONE_MODIFIERS,\n TEXT_NUMERIC_CLASS,\n TEXT_TRUNCATE_CLASS,\n TEXT_LINE_CLAMP_CLASS,\n TEXT_WRAP_MODIFIERS,\n TEXT_BOX_TRIM_MODIFIERS,\n TEXT_STRENGTH_MODIFIERS,\n TEXT_DENSITY_MODIFIERS,\n} from './TextConstants';\n\nconst DEFAULT_SIZE = '300';\nconst SEMANTIC_HEADING_ELEMENTS = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'];\n\n// Module-level flag to emit info only once per session\nlet hasEmittedHeadlineSemanticInfo = false;\n\n// Exported for testing purposes only\nexport const resetHeadlineSemanticInfoFlag = () => {\n hasEmittedHeadlineSemanticInfo = false;\n};\n\n/**\n * Dialtone text primitive that applies typography tokens based on semantic props.\n * @see https://dialtone.dialpad.com/components/text.html\n */\nexport default {\n name: 'DtText',\n\n props: {\n /**\n * HTML tag or component used for rendering.\n * @values span, p, h1, h2, h3, h4, h5, h6, label, div, component\n */\n as: {\n type: String,\n default: 'span',\n },\n\n /**\n * Typography kind mapping to headline/body/label/code token sets.\n * @values headline, body, label, code\n * @deprecated Use variant instead\n */\n kind: {\n type: String,\n default: null,\n validator: (value) => {\n return (\n value === null ||\n Object.prototype.hasOwnProperty.call(TEXT_KIND_MODIFIERS, value)\n );\n },\n },\n\n /**\n * Typography variant mapping to a complete token-backed composition.\n * @values headline-3xl, headline-2xl, headline-xl, headline-lg, headline-md, headline-sm, headline-xs, body-lg, body-md, body-sm, body-xs, label-lg, label-md, label-sm, label-xs, code-lg, code-md, code-sm, code-xs\n */\n variant: {\n type: String,\n default: null,\n validator: (value) => {\n return (\n value === null ||\n Object.prototype.hasOwnProperty.call(TEXT_VARIANT_MODIFIERS, value)\n );\n },\n },\n\n /**\n * Raw font-size token. Must be paired with `variant` for overrides or legacy `kind` for composition size.\n * @values 50, 75, 100, 125, 150, 200, 250, 300, 350, 400, 450, 500, 550, 600, 650, 700, 750, 800\n */\n size: {\n type: [String, Number],\n default: null,\n },\n\n /**\n * Overrides font-family. By default, no font-family class is emitted and text inherits naturally.\n * @values inherit, custom, sans, mono, expressive\n */\n family: {\n type: String,\n default: null,\n validator: (value) => {\n return (\n value === null ||\n Object.prototype.hasOwnProperty.call(TEXT_FAMILY_MODIFIERS, value)\n );\n },\n },\n\n /**\n * Applies italic font style when true.\n */\n italic: {\n type: Boolean,\n default: false,\n },\n\n /**\n * Semantic foreground color.\n * @values primary, secondary, tertiary, muted, disabled, placeholder, critical, critical-strong, positive, positive-strong, warning, info, info-strong, neutral-black, neutral-white\n */\n tone: {\n type: String,\n default: null,\n validator: (value) => {\n return (\n value === null ||\n Object.prototype.hasOwnProperty.call(TEXT_TONE_MODIFIERS, value)\n );\n },\n },\n\n /**\n * Logical text alignment. Requires block/inline-block context.\n * @values start, center, end, justify\n */\n align: {\n type: String,\n default: null,\n validator: (value) => {\n return (\n value === null ||\n Object.prototype.hasOwnProperty.call(TEXT_ALIGN_MODIFIERS, value)\n );\n },\n },\n\n /**\n * Enables single-line truncation (i.e. ellipsis) when true; requires block/inline-block context.\n */\n truncate: {\n type: Boolean,\n default: false,\n },\n\n /**\n * Applies multi-line truncation (i.e. clamp) when greater than zero; requires block/inline-block context.\n */\n maxLines: {\n type: Number,\n default: null,\n validator: (value) => {\n return value === null || (Number.isInteger(value) && value > 0);\n },\n },\n\n /**\n * Renders numeric content with tabular figures.\n */\n numeric: {\n type: Boolean,\n default: false,\n },\n\n /**\n * Controls text wrapping behavior.\n * @values wrap, nowrap, balance, pretty\n */\n wrap: {\n type: String,\n default: null,\n validator: (value) => {\n return (\n value === null ||\n Object.prototype.hasOwnProperty.call(TEXT_WRAP_MODIFIERS, value)\n );\n },\n },\n\n /**\n * Controls text-box-trim (leading space above/below text). Useful for tight component layouts.\n * @values start, end, both\n */\n textBoxTrim: {\n type: String,\n default: null,\n validator: (value) => {\n return (\n value === null ||\n Object.prototype.hasOwnProperty.call(TEXT_BOX_TRIM_MODIFIERS, value)\n );\n },\n },\n\n /**\n * Overrides font-weight. Applies to any kind/size combination.\n * @values bold, semibold, medium, normal\n */\n strength: {\n type: String,\n default: null,\n validator: (value) => {\n return (\n value === null ||\n Object.prototype.hasOwnProperty.call(TEXT_STRENGTH_MODIFIERS, value)\n );\n },\n },\n\n /**\n * Overrides line-height. Applies to any kind/size combination.\n * @values 100, 200, 300, 400, 500, 600\n */\n density: {\n type: [String, Number],\n default: null,\n validator: (value) => {\n return (\n value === null ||\n Object.prototype.hasOwnProperty.call(TEXT_DENSITY_MODIFIERS, value)\n );\n },\n },\n },\n\n computed: {\n textClasses() {\n const classes = ['d-text'];\n const variantClass = this.getVariantClass();\n if (variantClass) {\n classes.push(variantClass);\n }\n\n const fontSizeClass = this.getFontSizeClass();\n if (fontSizeClass) {\n classes.push(fontSizeClass);\n }\n\n const familyClass = this.getFamilyClass();\n if (familyClass) {\n classes.push(familyClass);\n }\n\n if (this.italic) {\n classes.push(TEXT_ITALIC_CLASS);\n }\n\n const alignClass = this.getAlignClass();\n if (alignClass) {\n classes.push(alignClass);\n }\n\n const toneClass = this.getToneClass();\n if (toneClass) {\n classes.push(toneClass);\n }\n\n if (this.truncate) {\n classes.push(TEXT_TRUNCATE_CLASS);\n }\n\n if (this.numeric) {\n classes.push(TEXT_NUMERIC_CLASS);\n }\n\n if (this.maxLines) {\n classes.push(TEXT_LINE_CLAMP_CLASS);\n }\n\n const wrapClass = this.getWrapClass();\n if (wrapClass) {\n classes.push(wrapClass);\n }\n\n const textBoxTrimClass = this.getTextBoxTrimClass();\n if (textBoxTrimClass) {\n classes.push(textBoxTrimClass);\n }\n\n const strengthClass = this.getStrengthClass();\n if (strengthClass) {\n classes.push(strengthClass);\n }\n\n const densityClass = this.getDensityClass();\n if (densityClass) {\n classes.push(densityClass);\n }\n\n return classes;\n },\n\n textStyles() {\n if (!this.maxLines) {\n return undefined;\n }\n\n return {\n '--dt-text-line-clamp': this.maxLines,\n };\n },\n },\n\n mounted() {\n // Emit info once per session when headline is used without semantic heading element\n if (\n !hasEmittedHeadlineSemanticInfo &&\n this.usesHeadlineVisualStyle() &&\n !SEMANTIC_HEADING_ELEMENTS.includes(this.as)\n ) {\n console.info(\n '[DtText] A headline text style is used without a semantic heading element. ' +\n 'Consider using as=\"h1|h2|h3|h4|h5|h6\" for better accessibility.',\n );\n hasEmittedHeadlineSemanticInfo = true;\n }\n },\n\n methods: {\n usesHeadlineVisualStyle() {\n if (this.variant) {\n return this.variant.startsWith('headline-');\n }\n\n return this.kind === 'headline';\n },\n\n usesLegacyKindSize() {\n return Boolean(this.kind && !this.variant);\n },\n\n getVariantClass() {\n if (this.variant) {\n return this.getModifierClass(\n this.variant,\n TEXT_VARIANT_MODIFIERS,\n 'variant',\n );\n }\n\n if (!this.kind) {\n return null;\n }\n\n if (\n !Object.prototype.hasOwnProperty.call(TEXT_KIND_MODIFIERS, this.kind)\n ) {\n console.warn(`[DtText] Unsupported kind \"${this.kind}\".`);\n return null;\n }\n\n const allowedSizes = TEXT_SIZE_MODIFIERS[this.kind] || [];\n const rawSize = this.size != null ? String(this.size) : null;\n const requestedSize = rawSize || DEFAULT_SIZE;\n let resolvedSize = requestedSize;\n\n if (!allowedSizes.includes(requestedSize)) {\n // Headline-only sizes (3xl, 2xl, xl, 500, 600, 700) throw an error when used with incompatible kinds\n if (TEXT_HEADLINE_ONLY_SIZES.includes(requestedSize)) {\n throw new Error(\n `[DtText] size=\"${requestedSize}\" is only valid for kind=\"headline\". ` +\n `Cannot use with kind=\"${this.kind}\".`,\n );\n }\n\n // Universal sizes fall back gracefully with a warning\n const fallbackSize = allowedSizes.includes(DEFAULT_SIZE)\n ? DEFAULT_SIZE\n : allowedSizes[0];\n if (fallbackSize) {\n resolvedSize = fallbackSize;\n }\n console.warn(\n `[DtText] size=\"${requestedSize}\" is not valid for kind=\"${this.kind}\". Using \"${resolvedSize}\" instead.`,\n );\n }\n\n if (!resolvedSize) {\n return null;\n }\n\n // Map numeric sizes to t-shirt CSS class suffix\n const cssSuffix = TEXT_SIZE_MAP[resolvedSize] || resolvedSize;\n return `${TEXT_KIND_MODIFIERS[this.kind]}--${cssSuffix}`;\n },\n\n getFontSizeClass() {\n if (this.size === null || this.size === undefined) {\n return null;\n }\n\n if (!this.variant && !this.kind) {\n console.warn(\n '[DtText] size must be paired with variant or legacy kind. ' +\n 'Prefer variant for typography composition; use size only as a variant override.',\n );\n return null;\n }\n\n if (this.usesLegacyKindSize()) {\n return null;\n }\n\n const size = String(this.size);\n const className = TEXT_FONT_SIZE_MODIFIERS[size];\n if (className) {\n return className;\n }\n\n console.warn(\n `[DtText] Unsupported size \"${size}\". Use a numeric font-size token.`,\n );\n return null;\n },\n\n getModifierClass(value, modifiers, propName) {\n if (value === null || value === undefined) {\n return null;\n }\n\n const className = modifiers[value];\n if (!className) {\n console.warn(`[DtText] Unsupported ${propName} \"${value}\".`);\n return null;\n }\n\n return className;\n },\n\n getAlignClass() {\n return this.getModifierClass(this.align, TEXT_ALIGN_MODIFIERS, 'align');\n },\n\n getToneClass() {\n return this.getModifierClass(this.tone, TEXT_TONE_MODIFIERS, 'tone');\n },\n\n getWrapClass() {\n return this.getModifierClass(this.wrap, TEXT_WRAP_MODIFIERS, 'wrap');\n },\n\n getTextBoxTrimClass() {\n return this.getModifierClass(\n this.textBoxTrim,\n TEXT_BOX_TRIM_MODIFIERS,\n 'textBoxTrim',\n );\n },\n\n getStrengthClass() {\n return this.getModifierClass(\n this.strength,\n TEXT_STRENGTH_MODIFIERS,\n 'strength',\n );\n },\n\n getDensityClass() {\n return this.getModifierClass(\n this.density,\n TEXT_DENSITY_MODIFIERS,\n 'density',\n );\n },\n\n getFamilyClass() {\n return this.getModifierClass(\n this.family,\n TEXT_FAMILY_MODIFIERS,\n 'family',\n );\n },\n },\n};\n</script>\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"text.js","names":[],"sources":["../../../components/Text/Text.vue"],"sourcesContent":["<template>\n <component\n :is=\"as\"\n data-qa=\"dt-text\"\n :class=\"textClasses\"\n :style=\"textStyles\"\n >\n <!-- @slot Default slot for text content -->\n <slot />\n </component>\n</template>\n\n<script>\nimport {\n TEXT_KIND_MODIFIERS,\n TEXT_VARIANT_MODIFIERS,\n TEXT_SIZE_MODIFIERS,\n TEXT_SIZE_MAP,\n TEXT_HEADLINE_ONLY_SIZES,\n TEXT_FONT_SIZE_MODIFIERS,\n TEXT_FAMILY_MODIFIERS,\n TEXT_ITALIC_CLASS,\n TEXT_ALIGN_MODIFIERS,\n TEXT_TONE_MODIFIERS,\n TEXT_NUMERIC_CLASS,\n TEXT_TRUNCATE_CLASS,\n TEXT_LINE_CLAMP_CLASS,\n TEXT_WRAP_MODIFIERS,\n TEXT_BOX_TRIM_MODIFIERS,\n TEXT_STRENGTH_MODIFIERS,\n TEXT_DENSITY_MODIFIERS,\n} from './TextConstants';\n\nconst DEFAULT_SIZE = '300';\nconst SEMANTIC_HEADING_ELEMENTS = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'];\n\n// Module-level flag to emit info only once per session\nlet hasEmittedHeadlineSemanticInfo = false;\n\n// Exported for testing purposes only\nexport const resetHeadlineSemanticInfoFlag = () => {\n hasEmittedHeadlineSemanticInfo = false;\n};\n\n/**\n * Dialtone text primitive that applies typography tokens based on semantic props.\n * @see https://dialtone.dialpad.com/components/text.html\n */\nexport default {\n name: 'DtText',\n\n props: {\n /**\n * HTML tag or component used for rendering.\n * @values span, p, strong, h1, h2, h3, h4, h5, h6, label, div, component\n */\n as: {\n type: String,\n default: 'span',\n },\n\n /**\n * Typography kind mapping to headline/body/label/code token sets.\n * @values headline, body, label, code\n * @deprecated Use variant instead\n */\n kind: {\n type: String,\n default: null,\n validator: (value) => {\n return (\n value === null ||\n Object.prototype.hasOwnProperty.call(TEXT_KIND_MODIFIERS, value)\n );\n },\n },\n\n /**\n * Typography variant mapping to a complete token-backed composition.\n * @values headline-3xl, headline-2xl, headline-xl, headline-lg, headline-md, headline-sm, headline-xs, body-lg, body-md, body-sm, body-xs, label-lg, label-md, label-sm, label-xs, code-lg, code-md, code-sm, code-xs\n */\n variant: {\n type: String,\n default: null,\n validator: (value) => {\n return (\n value === null ||\n Object.prototype.hasOwnProperty.call(TEXT_VARIANT_MODIFIERS, value)\n );\n },\n },\n\n /**\n * Raw font-size token. Must be paired with `variant` for overrides or legacy `kind` for composition size.\n * @values 50, 75, 100, 125, 150, 200, 250, 300, 350, 400, 450, 500, 550, 600, 650, 700, 750, 800\n */\n size: {\n type: [String, Number],\n default: null,\n },\n\n /**\n * Overrides font-family. By default, no font-family class is emitted and text inherits naturally.\n * @values inherit, custom, sans, mono, expressive\n */\n family: {\n type: String,\n default: null,\n validator: (value) => {\n return (\n value === null ||\n Object.prototype.hasOwnProperty.call(TEXT_FAMILY_MODIFIERS, value)\n );\n },\n },\n\n /**\n * Applies italic font style when true.\n */\n italic: {\n type: Boolean,\n default: false,\n },\n\n /**\n * Semantic foreground color.\n * @values primary, secondary, tertiary, muted, disabled, placeholder, critical, critical-strong, positive, positive-strong, warning, info, info-strong, neutral-black, neutral-white\n */\n tone: {\n type: String,\n default: null,\n validator: (value) => {\n return (\n value === null ||\n Object.prototype.hasOwnProperty.call(TEXT_TONE_MODIFIERS, value)\n );\n },\n },\n\n /**\n * Logical text alignment. Requires block/inline-block context.\n * @values start, center, end, justify\n */\n align: {\n type: String,\n default: null,\n validator: (value) => {\n return (\n value === null ||\n Object.prototype.hasOwnProperty.call(TEXT_ALIGN_MODIFIERS, value)\n );\n },\n },\n\n /**\n * Enables single-line truncation (i.e. ellipsis) when true; requires block/inline-block context.\n */\n truncate: {\n type: Boolean,\n default: false,\n },\n\n /**\n * Applies multi-line truncation (i.e. clamp) when greater than zero; requires block/inline-block context.\n */\n maxLines: {\n type: Number,\n default: null,\n validator: (value) => {\n return value === null || (Number.isInteger(value) && value > 0);\n },\n },\n\n /**\n * Renders numeric content with tabular figures.\n */\n numeric: {\n type: Boolean,\n default: false,\n },\n\n /**\n * Controls text wrapping behavior.\n * @values wrap, nowrap, balance, pretty\n */\n wrap: {\n type: String,\n default: null,\n validator: (value) => {\n return (\n value === null ||\n Object.prototype.hasOwnProperty.call(TEXT_WRAP_MODIFIERS, value)\n );\n },\n },\n\n /**\n * Controls text-box-trim (leading space above/below text). Useful for tight component layouts.\n * @values start, end, both\n */\n textBoxTrim: {\n type: String,\n default: null,\n validator: (value) => {\n return (\n value === null ||\n Object.prototype.hasOwnProperty.call(TEXT_BOX_TRIM_MODIFIERS, value)\n );\n },\n },\n\n /**\n * Overrides font-weight. Applies to any kind/size combination.\n * @values bold, semibold, medium, normal\n */\n strength: {\n type: String,\n default: null,\n validator: (value) => {\n return (\n value === null ||\n Object.prototype.hasOwnProperty.call(TEXT_STRENGTH_MODIFIERS, value)\n );\n },\n },\n\n /**\n * Overrides line-height. Applies to any kind/size combination.\n * @values 100, 200, 300, 400, 500, 600\n */\n density: {\n type: [String, Number],\n default: null,\n validator: (value) => {\n return (\n value === null ||\n Object.prototype.hasOwnProperty.call(TEXT_DENSITY_MODIFIERS, value)\n );\n },\n },\n },\n\n computed: {\n textClasses() {\n const classes = ['d-text'];\n const variantClass = this.getVariantClass();\n if (variantClass) {\n classes.push(variantClass);\n }\n\n const fontSizeClass = this.getFontSizeClass();\n if (fontSizeClass) {\n classes.push(fontSizeClass);\n }\n\n const familyClass = this.getFamilyClass();\n if (familyClass) {\n classes.push(familyClass);\n }\n\n if (this.italic) {\n classes.push(TEXT_ITALIC_CLASS);\n }\n\n const alignClass = this.getAlignClass();\n if (alignClass) {\n classes.push(alignClass);\n }\n\n const toneClass = this.getToneClass();\n if (toneClass) {\n classes.push(toneClass);\n }\n\n if (this.truncate) {\n classes.push(TEXT_TRUNCATE_CLASS);\n }\n\n if (this.numeric) {\n classes.push(TEXT_NUMERIC_CLASS);\n }\n\n if (this.maxLines) {\n classes.push(TEXT_LINE_CLAMP_CLASS);\n }\n\n const wrapClass = this.getWrapClass();\n if (wrapClass) {\n classes.push(wrapClass);\n }\n\n const textBoxTrimClass = this.getTextBoxTrimClass();\n if (textBoxTrimClass) {\n classes.push(textBoxTrimClass);\n }\n\n const strengthClass = this.getStrengthClass();\n if (strengthClass) {\n classes.push(strengthClass);\n }\n\n const densityClass = this.getDensityClass();\n if (densityClass) {\n classes.push(densityClass);\n }\n\n return classes;\n },\n\n textStyles() {\n if (!this.maxLines) {\n return undefined;\n }\n\n return {\n '--dt-text-line-clamp': this.maxLines,\n };\n },\n },\n\n mounted() {\n // Emit info once per session when headline is used without semantic heading element\n if (\n !hasEmittedHeadlineSemanticInfo &&\n this.usesHeadlineVisualStyle() &&\n !SEMANTIC_HEADING_ELEMENTS.includes(this.as)\n ) {\n console.info(\n '[DtText] A headline text style is used without a semantic heading element. ' +\n 'Consider using as=\"h1|h2|h3|h4|h5|h6\" for better accessibility.',\n );\n hasEmittedHeadlineSemanticInfo = true;\n }\n },\n\n methods: {\n usesHeadlineVisualStyle() {\n if (this.variant) {\n return this.variant.startsWith('headline-');\n }\n\n return this.kind === 'headline';\n },\n\n usesLegacyKindSize() {\n return Boolean(this.kind && !this.variant);\n },\n\n getVariantClass() {\n if (this.variant) {\n return this.getModifierClass(\n this.variant,\n TEXT_VARIANT_MODIFIERS,\n 'variant',\n );\n }\n\n if (!this.kind) {\n return null;\n }\n\n if (\n !Object.prototype.hasOwnProperty.call(TEXT_KIND_MODIFIERS, this.kind)\n ) {\n console.warn(`[DtText] Unsupported kind \"${this.kind}\".`);\n return null;\n }\n\n const allowedSizes = TEXT_SIZE_MODIFIERS[this.kind] || [];\n const rawSize = this.size != null ? String(this.size) : null;\n const requestedSize = rawSize || DEFAULT_SIZE;\n let resolvedSize = requestedSize;\n\n if (!allowedSizes.includes(requestedSize)) {\n // Headline-only sizes (3xl, 2xl, xl, 500, 600, 700) throw an error when used with incompatible kinds\n if (TEXT_HEADLINE_ONLY_SIZES.includes(requestedSize)) {\n throw new Error(\n `[DtText] size=\"${requestedSize}\" is only valid for kind=\"headline\". ` +\n `Cannot use with kind=\"${this.kind}\".`,\n );\n }\n\n // Universal sizes fall back gracefully with a warning\n const fallbackSize = allowedSizes.includes(DEFAULT_SIZE)\n ? DEFAULT_SIZE\n : allowedSizes[0];\n if (fallbackSize) {\n resolvedSize = fallbackSize;\n }\n console.warn(\n `[DtText] size=\"${requestedSize}\" is not valid for kind=\"${this.kind}\". Using \"${resolvedSize}\" instead.`,\n );\n }\n\n if (!resolvedSize) {\n return null;\n }\n\n // Map numeric sizes to t-shirt CSS class suffix\n const cssSuffix = TEXT_SIZE_MAP[resolvedSize] || resolvedSize;\n return `${TEXT_KIND_MODIFIERS[this.kind]}--${cssSuffix}`;\n },\n\n getFontSizeClass() {\n if (this.size === null || this.size === undefined) {\n return null;\n }\n\n if (!this.variant && !this.kind) {\n console.warn(\n '[DtText] size must be paired with variant or legacy kind. ' +\n 'Prefer variant for typography composition; use size only as a variant override.',\n );\n return null;\n }\n\n if (this.usesLegacyKindSize()) {\n return null;\n }\n\n const size = String(this.size);\n const className = TEXT_FONT_SIZE_MODIFIERS[size];\n if (className) {\n return className;\n }\n\n console.warn(\n `[DtText] Unsupported size \"${size}\". Use a numeric font-size token.`,\n );\n return null;\n },\n\n getModifierClass(value, modifiers, propName) {\n if (value === null || value === undefined) {\n return null;\n }\n\n const className = modifiers[value];\n if (!className) {\n console.warn(`[DtText] Unsupported ${propName} \"${value}\".`);\n return null;\n }\n\n return className;\n },\n\n getAlignClass() {\n return this.getModifierClass(this.align, TEXT_ALIGN_MODIFIERS, 'align');\n },\n\n getToneClass() {\n return this.getModifierClass(this.tone, TEXT_TONE_MODIFIERS, 'tone');\n },\n\n getWrapClass() {\n return this.getModifierClass(this.wrap, TEXT_WRAP_MODIFIERS, 'wrap');\n },\n\n getTextBoxTrimClass() {\n return this.getModifierClass(\n this.textBoxTrim,\n TEXT_BOX_TRIM_MODIFIERS,\n 'textBoxTrim',\n );\n },\n\n getStrengthClass() {\n return this.getModifierClass(\n this.strength,\n TEXT_STRENGTH_MODIFIERS,\n 'strength',\n );\n },\n\n getDensityClass() {\n return this.getModifierClass(\n this.density,\n TEXT_DENSITY_MODIFIERS,\n 'density',\n );\n },\n\n getFamilyClass() {\n return this.getModifierClass(\n this.family,\n TEXT_FAMILY_MODIFIERS,\n 'family',\n );\n },\n },\n};\n</script>\n"],"mappings":"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"}
|