ooxml-ui 1.12.3 → 1.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/custom-elements.json +395 -5
- package/dist/chrome/status-layout.d.ts +23 -0
- package/dist/{chunk-S6ZXU442.js → chunk-7E3HU7RL.js} +1 -1
- package/dist/{chunk-PXIYHFZ5.js → chunk-ANPFMQ6E.js} +1 -1
- package/dist/{chunk-UKXJLI3N.js → chunk-C3MXKNNK.js} +2431 -311
- package/dist/{chunk-MML6EKFH.js → chunk-C5F7454A.js} +5 -5
- package/dist/{chunk-OGNNNTKI.js → chunk-CWBSXK7P.js} +1 -1
- package/dist/{chunk-LHS5DYLT.js → chunk-DSQBXLMO.js} +1 -1
- package/dist/{chunk-L7JV5FVE.js → chunk-KNC2UEUR.js} +1 -1
- package/dist/{chunk-735S7V4M.js → chunk-LAVVSCRJ.js} +415 -116
- package/dist/{chunk-SPNWHKSR.js → chunk-LD3K2RDN.js} +7 -5
- package/dist/chunk-UBBC5FH7.js +31 -0
- package/dist/controls.d.ts +2 -1
- package/dist/controls.d.ts.map +1 -1
- package/dist/controls.js +4 -4
- package/dist/dialog/options-categories.d.ts +39 -0
- package/dist/dialog/options-categories.d.ts.map +1 -0
- package/dist/dialog/options-controls.d.ts +49 -0
- package/dist/dialog/options-controls.d.ts.map +1 -0
- package/dist/dialog/options-dialog.d.ts +76 -41
- package/dist/dialog/options-dialog.d.ts.map +1 -1
- package/dist/docx/auto-fit.d.ts +10 -0
- package/dist/docx/backstage-customize.d.ts +7 -0
- package/dist/docx/backstage-options.d.ts +13 -3
- package/dist/docx/backstage-pages.d.ts +0 -6
- package/dist/docx/backstage.d.ts +3 -0
- package/dist/docx/canvas-click.d.ts +7 -0
- package/dist/docx/content-control-calendar.d.ts +7 -0
- package/dist/docx/content-control-dialog.d.ts +7 -0
- package/dist/docx/content-control-view.d.ts +2 -0
- package/dist/docx/editor-core.d.ts +7 -0
- package/dist/docx/equation-commands.d.ts +17 -0
- package/dist/docx/equation-dialog.d.ts +7 -0
- package/dist/docx/format-dialogs.d.ts +1 -1
- package/dist/docx/insert-controller.d.ts +4 -0
- package/dist/docx/locales/en-app.d.ts +1 -0
- package/dist/docx/locales/en.d.ts +123 -0
- package/dist/docx/locales/objects.d.ts +37 -0
- package/dist/docx/locales/options.d.ts +11 -0
- package/dist/docx/locales/shapes.d.ts +101 -0
- package/dist/docx/localization-strings.d.ts +123 -0
- package/dist/docx/note-editor.d.ts +7 -1
- package/dist/docx/page-controller.d.ts +17 -3
- package/dist/docx/parts-controller.d.ts +27 -1
- package/dist/docx/print-caret-affinity.d.ts +15 -0
- package/dist/docx/print-editing-index.d.ts +1 -0
- package/dist/docx/print-editing.d.ts +4 -1
- package/dist/docx/print-float-geometry.d.ts +28 -0
- package/dist/docx/print-float-locate.d.ts +25 -0
- package/dist/docx/print-float-selection.d.ts +24 -0
- package/dist/docx/print-float-text.d.ts +8 -0
- package/dist/docx/print-keyboard-navigation.d.ts +4 -3
- package/dist/docx/print-layout-view.d.ts +8 -0
- package/dist/docx/print-layout.d.ts +1 -1
- package/dist/docx/print-note-editing.d.ts +47 -0
- package/dist/docx/print-page-window.d.ts +2 -1
- package/dist/docx/print-picture.d.ts +7 -0
- package/dist/docx/print-story-editing.d.ts +16 -0
- package/dist/docx/print-vertical-step.d.ts +7 -0
- package/dist/docx/ribbon-action.d.ts +15 -0
- package/dist/docx/ribbon-icons.d.ts +3 -0
- package/dist/docx/schema.d.ts +1 -1
- package/dist/docx/shape-commands.d.ts +40 -0
- package/dist/docx/shape-draw.d.ts +12 -0
- package/dist/docx/shape-format-ribbon.d.ts +4 -0
- package/dist/docx/shape-node-view.d.ts +4 -0
- package/dist/docx/shape-picker.d.ts +5 -0
- package/dist/docx/shape-text-dialog.d.ts +4 -0
- package/dist/docx/status-bar.d.ts +1 -1
- package/dist/docx/table-model-adapter.d.ts +1 -1
- package/dist/docx/table-navigation.d.ts +8 -0
- package/dist/docx.js +3578 -595
- package/dist/index.d.ts +1 -1
- package/dist/index.js +9 -9
- package/dist/pptx/{chart-3d-view-scene-MYQRQDNF.mjs → chart-3d-view-scene-BEAJCQIS.mjs} +2 -2
- package/dist/pptx/{chart-3d-view-scene-WX23DR2E.cjs → chart-3d-view-scene-CFUVOILD.cjs} +38 -38
- package/dist/pptx/{chunk-VFPVEVF4.cjs → chunk-2JTHIDMD.cjs} +173 -873
- package/dist/pptx/{chunk-ZN4T6CYA.cjs → chunk-4NBVWV6I.cjs} +134 -0
- package/dist/pptx/{chunk-TTX4TDHU.cjs → chunk-5DUBDWOU.cjs} +5580 -2709
- package/dist/pptx/{chunk-C5OJXCCB.cjs → chunk-5UGJC25J.cjs} +1 -1
- package/dist/pptx/{chunk-NAFUYAQP.mjs → chunk-DWUC6LZK.mjs} +1 -1
- package/dist/pptx/{chunk-5OMQM4GF.mjs → chunk-GUAP5VUN.mjs} +4799 -1979
- package/dist/pptx/{chunk-K3S2A64B.cjs → chunk-HULZNSHL.cjs} +13 -13
- package/dist/pptx/{chunk-FRB6BRVU.mjs → chunk-OJXPN2WX.mjs} +134 -0
- package/dist/pptx/{chunk-QCP2XYJW.mjs → chunk-P3YE5LT2.mjs} +1 -1
- package/dist/pptx/{chunk-DPOES4WM.mjs → chunk-VXKFXPCU.mjs} +116 -829
- package/dist/pptx/dom/index.cjs +253 -253
- package/dist/pptx/dom/index.mjs +8 -8
- package/dist/pptx/export/html2canvas-clone.cjs +2 -2
- package/dist/pptx/export/html2canvas-clone.mjs +1 -1
- package/dist/pptx/i18n/index.cjs +6 -6
- package/dist/pptx/i18n/index.mjs +1 -1
- package/dist/pptx/i18n/translations-en-table-layout.d.ts +3 -0
- package/dist/pptx/i18n/translations-en-table-layout.d.ts.map +1 -0
- package/dist/pptx/i18n/translations-en.d.ts.map +1 -1
- package/dist/pptx/index.cjs +3280 -3084
- package/dist/pptx/index.mjs +5 -5
- package/dist/pptx/render/chart-auto-title.d.ts +10 -15
- package/dist/pptx/render/chart-auto-title.d.ts.map +1 -1
- package/dist/pptx/render/chart-cartesian-bubbles.d.ts.map +1 -1
- package/dist/pptx/render/chart-combo-stock.cjs +3 -3
- package/dist/pptx/render/chart-combo-stock.mjs +1 -1
- package/dist/pptx/render/chart-data-label-text.d.ts +1 -1
- package/dist/pptx/render/chart-error-bars.d.ts.map +1 -1
- package/dist/pptx/render/chart-helpers.d.ts +3 -10
- package/dist/pptx/render/chart-helpers.d.ts.map +1 -1
- package/dist/pptx/render/chart-overlays-trendline-fit.d.ts +7 -9
- package/dist/pptx/render/chart-overlays-trendline-fit.d.ts.map +1 -1
- package/dist/pptx/render/chart-overlays.cjs +7 -7
- package/dist/pptx/render/chart-overlays.mjs +1 -1
- package/dist/pptx/render/chart-stock-candles.d.ts +0 -21
- package/dist/pptx/render/chart-stock-candles.d.ts.map +1 -1
- package/dist/pptx/render/chart-style-palette.d.ts +3 -28
- package/dist/pptx/render/chart-style-palette.d.ts.map +1 -1
- package/dist/pptx/render/chart-sunburst-hierarchy.d.ts +8 -28
- package/dist/pptx/render/chart-sunburst-hierarchy.d.ts.map +1 -1
- package/dist/pptx/render/chart-surface-treemap.cjs +4 -4
- package/dist/pptx/render/chart-surface-treemap.mjs +1 -1
- package/dist/pptx/render/chart-treemap-hierarchy.d.ts +7 -9
- package/dist/pptx/render/chart-treemap-hierarchy.d.ts.map +1 -1
- package/dist/pptx/render/chart-trendlines.d.ts +3 -17
- package/dist/pptx/render/chart-trendlines.d.ts.map +1 -1
- package/dist/pptx/render/chart-view-model-points.d.ts +2 -23
- package/dist/pptx/render/chart-view-model-points.d.ts.map +1 -1
- package/dist/pptx/render/chart-view-model.cjs +44 -44
- package/dist/pptx/render/chart-view-model.mjs +1 -1
- package/dist/pptx/render/chart-waterfall-map.cjs +6 -6
- package/dist/pptx/render/chart-waterfall-map.mjs +1 -1
- package/dist/pptx/render/comment-navigation.d.ts +51 -0
- package/dist/pptx/render/comment-navigation.d.ts.map +1 -0
- package/dist/pptx/render/customization/customization-catalog.d.ts +9 -2
- package/dist/pptx/render/customization/customization-catalog.d.ts.map +1 -1
- package/dist/pptx/render/customization/customization-controller.d.ts +9 -1
- package/dist/pptx/render/customization/customization-controller.d.ts.map +1 -1
- package/dist/pptx/render/customization/customization-descriptions.d.ts +5 -1
- package/dist/pptx/render/customization/customization-descriptions.d.ts.map +1 -1
- package/dist/pptx/render/customization/customization-entry-points.d.ts +46 -0
- package/dist/pptx/render/customization/customization-entry-points.d.ts.map +1 -0
- package/dist/pptx/render/customization/customization-reference.d.ts.map +1 -1
- package/dist/pptx/render/customization/customization-regions.d.ts +131 -0
- package/dist/pptx/render/customization/customization-regions.d.ts.map +1 -0
- package/dist/pptx/render/customization/customization-resolve-regions.d.ts +11 -0
- package/dist/pptx/render/customization/customization-resolve-regions.d.ts.map +1 -0
- package/dist/pptx/render/customization/customization-resolve.d.ts +21 -2
- package/dist/pptx/render/customization/customization-resolve.d.ts.map +1 -1
- package/dist/pptx/render/customization/customization-surfaces.d.ts +21 -0
- package/dist/pptx/render/customization/customization-surfaces.d.ts.map +1 -1
- package/dist/pptx/render/customization/customization-types.d.ts +28 -2
- package/dist/pptx/render/customization/customization-types.d.ts.map +1 -1
- package/dist/pptx/render/customization/index.d.ts +2 -0
- package/dist/pptx/render/customization/index.d.ts.map +1 -1
- package/dist/pptx/render/customization/ribbon-control-catalog-core.d.ts +34 -2
- package/dist/pptx/render/customization/ribbon-control-catalog-core.d.ts.map +1 -1
- package/dist/pptx/render/customization/ribbon-control-catalog-tail.d.ts +61 -0
- package/dist/pptx/render/customization/ribbon-control-catalog-tail.d.ts.map +1 -1
- package/dist/pptx/render/customization/ribbon-control-catalog.d.ts +95 -2
- package/dist/pptx/render/customization/ribbon-control-catalog.d.ts.map +1 -1
- package/dist/pptx/render/customization/ribbon-control-visibility.d.ts +6 -1
- package/dist/pptx/render/customization/ribbon-control-visibility.d.ts.map +1 -1
- package/dist/pptx/render/editor-chrome/ribbon-css.d.ts +1 -1
- package/dist/pptx/render/editor-chrome/ribbon-css.d.ts.map +1 -1
- package/dist/pptx/render/index.d.ts +3 -1
- package/dist/pptx/render/index.d.ts.map +1 -1
- package/dist/pptx/render/morph-plan.d.ts.map +1 -1
- package/dist/pptx/render/ole-actions.d.ts +5 -3
- package/dist/pptx/render/ole-actions.d.ts.map +1 -1
- package/dist/pptx/render/options/index.d.ts +2 -0
- package/dist/pptx/render/options/index.d.ts.map +1 -1
- package/dist/pptx/render/options/options-dialog-binding.d.ts +60 -0
- package/dist/pptx/render/options/options-dialog-binding.d.ts.map +1 -0
- package/dist/pptx/render/options/options-dialog-model.d.ts +35 -0
- package/dist/pptx/render/options/options-dialog-model.d.ts.map +1 -0
- package/dist/pptx/render/review-comment-commands.d.ts +42 -0
- package/dist/pptx/render/review-comment-commands.d.ts.map +1 -0
- package/dist/pptx/render/ribbon-galleries/gallery-placements.d.ts.map +1 -1
- package/dist/pptx/render/ribbon-galleries/gallery-registry.d.ts.map +1 -1
- package/dist/pptx/render/ribbon-galleries/gallery-types.d.ts +9 -1
- package/dist/pptx/render/ribbon-galleries/gallery-types.d.ts.map +1 -1
- package/dist/pptx/render/ribbon-galleries/index.d.ts +2 -0
- package/dist/pptx/render/ribbon-galleries/index.d.ts.map +1 -1
- package/dist/pptx/render/ribbon-galleries/table-layout-commands.d.ts +7 -0
- package/dist/pptx/render/ribbon-galleries/table-layout-commands.d.ts.map +1 -0
- package/dist/pptx/render/ribbon-galleries/table-layout-ops.d.ts +64 -0
- package/dist/pptx/render/ribbon-galleries/table-layout-ops.d.ts.map +1 -0
- package/dist/pptx/render/ribbon-galleries/table-text-direction-gallery.d.ts +3 -0
- package/dist/pptx/render/ribbon-galleries/table-text-direction-gallery.d.ts.map +1 -0
- package/dist/pptx/render/ribbon-insert-layout.d.ts +56 -0
- package/dist/pptx/render/ribbon-insert-layout.d.ts.map +1 -0
- package/dist/pptx/render/ribbon-insert-state.d.ts +42 -2
- package/dist/pptx/render/ribbon-insert-state.d.ts.map +1 -1
- package/dist/pptx/render/ribbon-review-commands.d.ts +7 -0
- package/dist/pptx/render/ribbon-review-commands.d.ts.map +1 -1
- package/dist/pptx/render/toolbar-actions.d.ts +1 -1
- package/dist/pptx/render/toolbar-actions.d.ts.map +1 -1
- package/dist/pptx/render/viewer-props-manifest.d.ts +54 -0
- package/dist/pptx/render/viewer-props-manifest.d.ts.map +1 -0
- package/dist/pptx/web-components/index.d.ts.map +1 -1
- package/dist/pptx/web-components/office-aliases.d.ts +13 -0
- package/dist/pptx/web-components/office-aliases.d.ts.map +1 -1
- package/dist/pptx/web-components/office-token-bridge.d.ts +1 -1
- package/dist/pptx/web-components/office-token-bridge.d.ts.map +1 -1
- package/dist/pptx/web-components/options-dialog.d.ts +7 -0
- package/dist/pptx/web-components/options-dialog.d.ts.map +1 -0
- package/dist/pptx/web-components/ribbon-insert-dom.d.ts +28 -1
- package/dist/pptx/web-components/ribbon-insert-dom.d.ts.map +1 -1
- package/dist/pptx/web-components/ribbon-insert-icons.d.ts.map +1 -1
- package/dist/pptx/web-components/ribbon-insert-styles.d.ts.map +1 -1
- package/dist/pptx/web-components/ribbon-insert-table-picker.d.ts +16 -0
- package/dist/pptx/web-components/ribbon-insert-table-picker.d.ts.map +1 -0
- package/dist/pptx/web-components/ribbon-insert-view.d.ts +2 -1
- package/dist/pptx/web-components/ribbon-insert-view.d.ts.map +1 -1
- package/dist/pptx/web-components/ribbon-overflow.d.ts.map +1 -1
- package/dist/presence.js +3 -3
- package/dist/ribbon/auto-collapse.d.ts +8 -0
- package/dist/ribbon/auto-collapse.d.ts.map +1 -0
- package/dist/ribbon/group-overflow.d.ts +7 -0
- package/dist/ribbon/group-overflow.d.ts.map +1 -1
- package/dist/ribbon/overflow.d.ts +7 -0
- package/dist/ribbon/overflow.d.ts.map +1 -1
- package/dist/ribbon/ribbon-tabs.d.ts +5 -0
- package/dist/ribbon/ribbon-tabs.d.ts.map +1 -1
- package/dist/ribbon/scroll-more.d.ts +17 -0
- package/dist/ribbon/scroll-more.d.ts.map +1 -0
- package/dist/smartart.js +3 -3
- package/dist/teams/activity-feed.d.ts +36 -0
- package/dist/teams/app/activity.d.ts +5 -0
- package/dist/teams/app/calendar-app.d.ts +2 -0
- package/dist/teams/app/chat-app.d.ts +11 -0
- package/dist/teams/app/chat-people-dialog.d.ts +38 -0
- package/dist/teams/app/controller.d.ts +3 -2
- package/dist/teams/app/dialog-base.d.ts +18 -0
- package/dist/teams/app/meeting-details.d.ts +63 -0
- package/dist/teams/app/meeting-dialog.d.ts +103 -0
- package/dist/teams/app/new-chat-dialog.d.ts +42 -0
- package/dist/teams/app/notify-delivery.d.ts +28 -0
- package/dist/teams/app/pinned-bar.d.ts +24 -0
- package/dist/teams/app/profile-menu.d.ts +18 -1
- package/dist/teams/app/settings-notifications.d.ts +9 -0
- package/dist/teams/app/store.d.ts +1 -1
- package/dist/teams/app/teams-app.d.ts +72 -5
- package/dist/teams/app/teams-settings.d.ts +5 -1
- package/dist/teams/app/thread-pane.d.ts +1 -1
- package/dist/teams/app-rail.d.ts +17 -3
- package/dist/teams/avatar.d.ts +2 -2
- package/dist/teams/base.d.ts +2 -0
- package/dist/teams/calendar-agenda.d.ts +30 -0
- package/dist/teams/calendar-view.d.ts +61 -0
- package/dist/teams/chat-composer.d.ts +32 -2
- package/dist/teams/chat-list.d.ts +41 -3
- package/dist/teams/chat-sidebar.d.ts +25 -0
- package/dist/teams/index.d.ts +6 -1
- package/dist/teams/people-picker.d.ts +37 -0
- package/dist/teams.js +6 -6
- package/dist/theme.js +2 -2
- package/dist/tokens.d.ts +7 -5
- package/dist/tokens.d.ts.map +1 -1
- package/dist/visio/locales/de-commands.d.ts +2 -0
- package/dist/visio/locales/de-text.d.ts +2 -0
- package/dist/visio/locales/en-commands.d.ts +2 -0
- package/dist/visio/locales/en-text.d.ts +2 -0
- package/dist/visio/locales/es-commands.d.ts +2 -0
- package/dist/visio/locales/es-text.d.ts +2 -0
- package/dist/visio/locales/fr-commands.d.ts +2 -0
- package/dist/visio/locales/fr-text.d.ts +2 -0
- package/dist/visio/locales/zh-CN-commands.d.ts +2 -0
- package/dist/visio/locales/zh-CN-text.d.ts +2 -0
- package/dist/visio/ribbon-home.d.ts +1 -1
- package/dist/visio/ribbon-locale.d.ts +11 -0
- package/dist/visio/ribbon-localize.d.ts +9 -0
- package/dist/visio/ribbon-tab-cue.d.ts +8 -0
- package/dist/visio/shapes-document.d.ts +5 -0
- package/dist/visio/shapes-files-ui.d.ts +13 -0
- package/dist/visio/shapes-master-list.d.ts +5 -0
- package/dist/visio/shapes-sections.d.ts +1 -4
- package/dist/visio/stencil-files.d.ts +36 -0
- package/dist/visio/styles.d.ts +1 -1
- package/dist/visio/viewer-chrome.d.ts +3 -3
- package/dist/visio/viewer-element.d.ts +2 -0
- package/dist/visio/viewer-gesture-state.d.ts +54 -0
- package/dist/visio/viewer-options-categories.d.ts +8 -0
- package/dist/visio/viewer-options.d.ts +3 -7
- package/dist/visio/viewer-touch-gestures.d.ts +17 -0
- package/dist/visio/viewer-touch-hit.d.ts +3 -0
- package/dist/visio/viewer-touch-long-press.d.ts +13 -0
- package/dist/visio/viewer-touch-math.d.ts +44 -0
- package/dist/visio.js +2425 -295
- package/dist/xlsx/backstage/index.d.ts +3 -0
- package/dist/xlsx/backstage/options-customize.d.ts +7 -0
- package/dist/xlsx/backstage/options-dialog.d.ts +13 -0
- package/dist/xlsx/commands/slicers.d.ts +9 -0
- package/dist/xlsx/commands/view.d.ts +3 -0
- package/dist/xlsx/dialogs/pivot-field-settings.d.ts +7 -0
- package/dist/xlsx/dialogs/pivot-group-dates.d.ts +6 -0
- package/dist/xlsx/dialogs/pivot-group.d.ts +3 -0
- package/dist/xlsx/dialogs/pivot-rows.d.ts +21 -0
- package/dist/xlsx/dialogs/pivot-values.d.ts +1 -1
- package/dist/xlsx/dialogs/scenario-manager.d.ts +2 -0
- package/dist/xlsx/dialogs/slicers.d.ts +9 -0
- package/dist/xlsx/dialogs/styles.d.ts +1 -1
- package/dist/xlsx/dialogs/what-if.d.ts +5 -0
- package/dist/xlsx/grid/page-break-layer.d.ts +3 -0
- package/dist/xlsx/grid/slicer.d.ts +22 -0
- package/dist/xlsx/grid/styles.d.ts +1 -1
- package/dist/xlsx/grid/timeline.d.ts +12 -0
- package/dist/xlsx/modules.d.ts +1 -0
- package/dist/xlsx/page-views/index.d.ts +7 -0
- package/dist/xlsx/page-views/page-layout-bands.d.ts +17 -0
- package/dist/xlsx/page-views/page-layout-css.d.ts +1 -0
- package/dist/xlsx/page-views/page-layout-editor.d.ts +21 -0
- package/dist/xlsx/page-views/page-layout-rulers.d.ts +3 -0
- package/dist/xlsx/page-views/page-layout-view.d.ts +8 -0
- package/dist/xlsx/print-pages.d.ts +7 -1
- package/dist/xlsx/ribbon/ribbon.d.ts +1 -1
- package/dist/xlsx/ribbon/tabs/contextual.d.ts +4 -0
- package/dist/xlsx/status-bar.d.ts +1 -1
- package/dist/xlsx.js +3015 -546
- package/package.json +2 -2
- package/dist/pptx/render/chart-number-format-pattern.d.ts +0 -35
- package/dist/pptx/render/chart-number-format-pattern.d.ts.map +0 -1
- package/dist/pptx/render/chart-number-format.d.ts +0 -21
- package/dist/pptx/render/chart-number-format.d.ts.map +0 -1
- package/dist/pptx/render/chart-waterfall-layout.d.ts +0 -20
- package/dist/pptx/render/chart-waterfall-layout.d.ts.map +0 -1
- package/dist/teams/app/navigation-drawer.d.ts +0 -26
- package/dist/xlsx/backstage/pages-options.d.ts +0 -7
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { THEME_CSS, installOfficeUiTheme } from './chunk-
|
|
2
|
-
import { defineMenuButton, defineMenuItem, registerControls, defineSwitch } from './chunk-
|
|
1
|
+
import { THEME_CSS, installOfficeUiTheme } from './chunk-7E3HU7RL.js';
|
|
2
|
+
import { defineMenuButton, defineMenuItem, registerControls, defineSwitch } from './chunk-LAVVSCRJ.js';
|
|
3
3
|
import { registerIcon, getIcon } from './chunk-M6GF5ED2.js';
|
|
4
|
-
import { initialsOf, definePresence } from './chunk-
|
|
5
|
-
import { definer, OfficeElement, controlStyles } from './chunk-
|
|
6
|
-
import {
|
|
4
|
+
import { initialsOf, definePresence } from './chunk-KNC2UEUR.js';
|
|
5
|
+
import { definer, OfficeElement, controlStyles } from './chunk-CWBSXK7P.js';
|
|
6
|
+
import { nothing, html, LitElement, unsafeCSS, svg } from 'lit';
|
|
7
|
+
import { filterActivity, ACTIVITY_FILTERS, describeActivity, localZone, startOfDay, occurrencesBetween, DAY_MS as DAY_MS$1, dayKey, zonedToUtc, viewDays, zonedParts, shiftAnchor, layoutDay, mentionQueryAt, filterMentionTargets, insertMention, MAX_ATTACHMENTS, mentionsUser, mentionSegments, detectContentKind, contentUrl, readContent, sortFiles, filterFiles, parseServerConfig, STATUS_DURATIONS, STATUS_DURATION_LABELS, PRESENCE_LABELS, MAX_STATUS_MESSAGE_CHARS, isPresenceStatus, PRESENCE_STATUSES, isStatusDuration, IDLE_MINUTE_CHOICES, sanitizeChannelName, MAX_CHANNEL_NAME_CHARS, MAX_CHANNEL_TOPIC_CHARS, MAX_CHAT_MEMBERS, occurrenceAt, MAX_RECURRENCE_COUNT, MINUTE_MS, MAX_MEETING_TITLE, MAX_MEETING_DESCRIPTION, markdownBlocks, createTeamsClient, sanitizeAttachment, markdownInline } from 'ooxml-core/teams';
|
|
7
8
|
import { repeat } from 'lit/directives/repeat.js';
|
|
8
9
|
import { live } from 'lit/directives/live.js';
|
|
9
|
-
import { MAX_ATTACHMENTS, detectContentKind, contentUrl, readContent, sortFiles, filterFiles, parseServerConfig, sanitizeChannelName, MAX_CHANNEL_NAME_CHARS, MAX_CHANNEL_TOPIC_CHARS, markdownBlocks, createTeamsClient, sanitizeAttachment, markdownInline } from 'ooxml-core/teams';
|
|
10
10
|
import { keyed } from 'lit/directives/keyed.js';
|
|
11
11
|
|
|
12
12
|
// raw-css:/home/runner/work/ooxml/ooxml/src/ui/src/teams/reset.css?raw
|
|
@@ -42,8 +42,20 @@ function formatSize(bytes) {
|
|
|
42
42
|
if (bytes < 1048576) return `${Math.round(bytes / 1024)} KB`;
|
|
43
43
|
return `${(bytes / 1048576).toFixed(1)} MB`;
|
|
44
44
|
}
|
|
45
|
+
var timeOnly = (ts) => new Date(ts).toLocaleTimeString([], { hour: "numeric", minute: "2-digit" });
|
|
46
|
+
function formatWhen(start, end) {
|
|
47
|
+
const day = new Date(start).toLocaleDateString([], {
|
|
48
|
+
weekday: "short",
|
|
49
|
+
month: "short",
|
|
50
|
+
day: "numeric"
|
|
51
|
+
});
|
|
52
|
+
const sameDay = new Date(start).toDateString() === new Date(end).toDateString();
|
|
53
|
+
const tail = sameDay ? timeOnly(end) : `${new Date(end).toLocaleDateString([], { month: "short", day: "numeric" })}, ${timeOnly(end)}`;
|
|
54
|
+
return `${day}, ${timeOnly(start)} - ${tail}`;
|
|
55
|
+
}
|
|
45
56
|
var GLYPHS = {
|
|
46
|
-
|
|
57
|
+
back: "M12.5 4 6.5 10l6 6",
|
|
58
|
+
pin: "M7 3h6l-1 5 3 3H5l3-3ZM10 11v6",
|
|
47
59
|
send: "M3 10 17 3l-4 14-3-6Zm7 1 7-8",
|
|
48
60
|
paperclip: "M15 9.5l-5.5 5.5a3.5 3.5 0 0 1-5-5l6-6a2.3 2.3 0 0 1 3.3 3.3l-6 6a1.2 1.2 0 0 1-1.7-1.7L11 6",
|
|
49
61
|
smile: "M3 10a7 7 0 1 0 14 0 7 7 0 1 0-14 0M7.5 8v.5M12.5 8v.5M7 12c1.5 2 4.5 2 6 0",
|
|
@@ -61,7 +73,9 @@ var GLYPHS = {
|
|
|
61
73
|
screenShare: "M3 4h14v9H3ZM7 17h6M10 13v4M10 10V6M8 8l2-2 2 2",
|
|
62
74
|
hand: "M7 10V4.5a1 1 0 0 1 2 0V9M9 9V3.5a1 1 0 0 1 2 0V9M11 9V4.5a1 1 0 0 1 2 0V10M13 8.5a1 1 0 0 1 2 0V12a5 5 0 0 1-5 5h-.5A4.5 4.5 0 0 1 5 13.5L4 10.5a1 1 0 0 1 2-.5l1 2",
|
|
63
75
|
phoneOff: "M3 11c4-3 10-3 14 0l-1.5 2.5-3-1V10a9 9 0 0 0-5 0v2.5l-3 1Z",
|
|
64
|
-
chat: "M3 4h14v9H8l-5 4z"
|
|
76
|
+
chat: "M3 4h14v9H8l-5 4z",
|
|
77
|
+
bell: "M5 14h10l-1.5-2V8.5a3.5 3.5 0 0 0-7 0V12ZM8.5 16.5a1.5 1.5 0 0 0 3 0",
|
|
78
|
+
at: "M13 10a3 3 0 1 1-6 0 3 3 0 0 1 6 0ZM13 10v1.2a1.8 1.8 0 0 0 3.6 0V10a6.6 6.6 0 1 0-2.6 5.2"
|
|
65
79
|
};
|
|
66
80
|
for (const [name, d] of Object.entries(GLYPHS)) registerIcon(name, d);
|
|
67
81
|
function icon(name) {
|
|
@@ -72,63 +86,244 @@ function icon(name) {
|
|
|
72
86
|
</svg>`;
|
|
73
87
|
}
|
|
74
88
|
|
|
89
|
+
// raw-css:/home/runner/work/ooxml/ooxml/src/ui/src/teams/activity-feed.css?raw
|
|
90
|
+
var activity_feed_default = ":host {\n display: flex;\n flex-direction: column;\n min-height: 0;\n overflow: hidden;\n}\nheader {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--office-space-2);\n padding: var(--office-space-3) var(--office-space-3) var(--office-space-1);\n}\nh2 {\n margin: 0;\n font-size: var(--office-font-size-lg);\n font-weight: var(--office-font-weight-bold);\n}\n.read-all {\n padding: var(--office-space-1) var(--office-space-2);\n border: 0;\n border-radius: var(--office-radius);\n background: transparent;\n color: var(--office-teams-brand);\n font-size: var(--office-font-size-sm);\n}\n.read-all:hover:not(:disabled) {\n background: var(--office-selected);\n}\n.read-all:disabled {\n color: var(--office-teams-text-subtle);\n cursor: default;\n}\n.filters {\n display: flex;\n flex-wrap: wrap;\n gap: var(--office-space-1);\n padding: var(--office-space-1) var(--office-space-3) var(--office-space-2);\n}\n.filters button {\n display: inline-flex;\n align-items: center;\n gap: var(--office-space-1);\n padding: var(--office-space-1) var(--office-space-3);\n border: var(--office-border-width) solid var(--office-teams-divider);\n border-radius: var(--office-radius-full);\n background: transparent;\n font-size: var(--office-font-size-sm);\n}\n.filters button:hover {\n background: var(--office-selected);\n}\n.filters button[aria-pressed='true'] {\n border-color: var(--office-teams-brand);\n background: var(--office-teams-brand-subtle);\n color: var(--office-teams-brand);\n font-weight: var(--office-font-weight-bold);\n}\n.count {\n min-width: 1.4em;\n padding: 0 var(--office-space-1);\n border-radius: var(--office-radius-full);\n background: var(--office-teams-brand);\n color: var(--office-teams-brand-foreground);\n font-size: var(--office-font-size-3xs);\n line-height: 1.6;\n text-align: center;\n}\nul {\n flex: 1;\n min-height: 0;\n margin: 0;\n padding: 0 var(--office-space-2) var(--office-space-2);\n overflow-y: auto;\n list-style: none;\n}\nli {\n position: relative;\n}\n.item {\n display: flex;\n align-items: flex-start;\n gap: var(--office-space-3);\n width: 100%;\n padding: var(--office-space-2) var(--office-space-3);\n border: 0;\n border-radius: var(--office-radius-md);\n background: transparent;\n color: inherit;\n text-align: start;\n}\n.item:hover {\n background: var(--office-selected);\n}\n.item[aria-current='true'] {\n background: var(--office-teams-brand-subtle);\n}\n.face {\n position: relative;\n flex: none;\n}\n.kind {\n position: absolute;\n inset-block-end: calc(-1 * var(--office-space-1));\n inset-inline-end: calc(-1 * var(--office-space-1));\n display: grid;\n place-items: center;\n width: 1.5em;\n height: 1.5em;\n border-radius: var(--office-radius-full);\n background: var(--office-teams-brand);\n color: var(--office-teams-brand-foreground);\n}\n.kind svg {\n width: 0.9em;\n height: 0.9em;\n}\n.text {\n display: flex;\n flex: 1;\n flex-direction: column;\n min-width: 0;\n}\n.line {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\nli[data-unread='true'] .line {\n font-weight: var(--office-font-weight-bold);\n}\n.preview {\n overflow: hidden;\n color: var(--office-teams-text-subtle);\n font-size: var(--office-font-size-sm);\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.when {\n display: flex;\n flex: none;\n flex-direction: column;\n align-items: flex-end;\n gap: var(--office-space-1);\n color: var(--office-teams-text-subtle);\n font-size: var(--office-font-size-xs);\n}\n.dot {\n width: 0.7em;\n height: 0.7em;\n border-radius: var(--office-radius-full);\n background: var(--office-teams-brand);\n}\n.toggle {\n position: absolute;\n inset-block-end: var(--office-space-1);\n inset-inline-end: var(--office-space-2);\n display: none;\n place-items: center;\n width: 2em;\n height: 2em;\n border: 0;\n border-radius: var(--office-radius);\n background: var(--office-popover);\n color: var(--office-teams-text-subtle);\n box-shadow: var(--office-shadow-teams);\n}\nli:hover .toggle,\nli:focus-within .toggle {\n display: grid;\n}\n.empty {\n margin: 0;\n padding: var(--office-space-4);\n color: var(--office-teams-text-subtle);\n text-align: center;\n}\n@media (pointer: coarse) {\n .filters button,\n .read-all {\n min-height: var(--office-touch-target, 44px);\n }\n .toggle {\n display: grid;\n width: var(--office-touch-target, 44px);\n height: var(--office-touch-target, 44px);\n }\n}\n";
|
|
91
|
+
|
|
92
|
+
// src/teams/activity-feed.ts
|
|
93
|
+
var FILTER_LABEL = {
|
|
94
|
+
all: "All",
|
|
95
|
+
unread: "Unread",
|
|
96
|
+
mentions: "Mentions",
|
|
97
|
+
replies: "Replies",
|
|
98
|
+
reactions: "Reactions"
|
|
99
|
+
};
|
|
100
|
+
var KIND_ICON = {
|
|
101
|
+
mention: "at",
|
|
102
|
+
reply: "reply",
|
|
103
|
+
reaction: "smile",
|
|
104
|
+
pin: "pin",
|
|
105
|
+
meeting: "calendar"
|
|
106
|
+
};
|
|
107
|
+
var EMPTY = {
|
|
108
|
+
all: "No activity yet. Mentions, replies, reactions and pinned messages show up here.",
|
|
109
|
+
unread: "You are all caught up.",
|
|
110
|
+
mentions: "Nobody has mentioned you yet.",
|
|
111
|
+
replies: "No replies to your messages or followed threads yet.",
|
|
112
|
+
reactions: "No reactions to your messages yet."
|
|
113
|
+
};
|
|
114
|
+
function activityTime(ts, now = Date.now()) {
|
|
115
|
+
const day = dayLabel(ts, now);
|
|
116
|
+
if (day === "Today") return formatTime(ts);
|
|
117
|
+
if (day === "Yesterday") return day;
|
|
118
|
+
return new Date(ts).toLocaleDateString([], { month: "short", day: "numeric" });
|
|
119
|
+
}
|
|
120
|
+
var OfficeUiActivityFeed = class extends TeamsElement {
|
|
121
|
+
static styles = withStyles(activity_feed_default);
|
|
122
|
+
static properties = {
|
|
123
|
+
items: { attribute: false },
|
|
124
|
+
filter: { type: String, reflect: true },
|
|
125
|
+
selectedId: { type: String, attribute: "selected-id" }
|
|
126
|
+
};
|
|
127
|
+
constructor() {
|
|
128
|
+
super();
|
|
129
|
+
this.items = [];
|
|
130
|
+
this.filter = "all";
|
|
131
|
+
this.selectedId = "";
|
|
132
|
+
}
|
|
133
|
+
get unread() {
|
|
134
|
+
return this.items.filter((item) => !item.read).length;
|
|
135
|
+
}
|
|
136
|
+
render() {
|
|
137
|
+
const shown = filterActivity(this.items, this.filter);
|
|
138
|
+
const unread = this.unread;
|
|
139
|
+
return html`
|
|
140
|
+
<header>
|
|
141
|
+
<h2>Activity</h2>
|
|
142
|
+
<button
|
|
143
|
+
type="button"
|
|
144
|
+
class="read-all"
|
|
145
|
+
?disabled=${unread === 0}
|
|
146
|
+
@click=${() => this.fire("office-activity-read-all", {})}
|
|
147
|
+
>
|
|
148
|
+
Mark all as read
|
|
149
|
+
</button>
|
|
150
|
+
</header>
|
|
151
|
+
<div class="filters" role="group" aria-label="Filter activity">
|
|
152
|
+
${ACTIVITY_FILTERS.map(
|
|
153
|
+
(value) => html`<button
|
|
154
|
+
type="button"
|
|
155
|
+
aria-pressed=${String(this.filter === value)}
|
|
156
|
+
@click=${() => {
|
|
157
|
+
this.filter = value;
|
|
158
|
+
this.fire("office-activity-filter", { filter: value });
|
|
159
|
+
}}
|
|
160
|
+
>
|
|
161
|
+
${FILTER_LABEL[value]}${value === "unread" && unread ? html` <span class="count">${unread}</span>` : nothing}
|
|
162
|
+
</button>`
|
|
163
|
+
)}
|
|
164
|
+
</div>
|
|
165
|
+
${shown.length ? html`<ul aria-label="Activity feed">
|
|
166
|
+
${shown.map((item) => this.row(item))}
|
|
167
|
+
</ul>` : html`<p class="empty" role="status">${EMPTY[this.filter]}</p>`}
|
|
168
|
+
`;
|
|
169
|
+
}
|
|
170
|
+
row(item) {
|
|
171
|
+
const line = describeActivity(item);
|
|
172
|
+
return html`<li data-unread=${String(!item.read)} data-kind=${item.kind}>
|
|
173
|
+
<button
|
|
174
|
+
type="button"
|
|
175
|
+
class="item"
|
|
176
|
+
aria-current=${this.selectedId === item.id ? "true" : "false"}
|
|
177
|
+
aria-label=${`${item.read ? "" : "Unread. "}${line}. ${item.preview}`}
|
|
178
|
+
@click=${() => this.fire("office-activity-open", { id: item.id })}
|
|
179
|
+
>
|
|
180
|
+
<span class="face">
|
|
181
|
+
<office-ui-avatar
|
|
182
|
+
size="md"
|
|
183
|
+
name=${item.actorName}
|
|
184
|
+
seed=${item.actorId}
|
|
185
|
+
></office-ui-avatar>
|
|
186
|
+
<span class="kind" aria-hidden="true">${icon(KIND_ICON[item.kind])}</span>
|
|
187
|
+
</span>
|
|
188
|
+
<span class="text">
|
|
189
|
+
<span class="line">${line}</span>
|
|
190
|
+
<span class="preview">${item.preview}</span>
|
|
191
|
+
</span>
|
|
192
|
+
<span class="when">
|
|
193
|
+
<time datetime=${new Date(item.ts).toISOString()}>${activityTime(item.ts)}</time>
|
|
194
|
+
${item.read ? nothing : html`<span class="dot" aria-hidden="true"></span>`}
|
|
195
|
+
</span>
|
|
196
|
+
</button>
|
|
197
|
+
<button
|
|
198
|
+
type="button"
|
|
199
|
+
class="toggle"
|
|
200
|
+
title=${item.read ? "Mark as unread" : "Mark as read"}
|
|
201
|
+
aria-label=${item.read ? "Mark as unread" : "Mark as read"}
|
|
202
|
+
@click=${() => this.fire("office-activity-read", { id: item.id, read: !item.read })}
|
|
203
|
+
>
|
|
204
|
+
${icon(item.read ? "bell" : "check")}
|
|
205
|
+
</button>
|
|
206
|
+
</li>`;
|
|
207
|
+
}
|
|
208
|
+
};
|
|
209
|
+
var defineActivityFeed = definer("office-ui-activity-feed", () => OfficeUiActivityFeed);
|
|
210
|
+
|
|
75
211
|
// raw-css:/home/runner/work/ooxml/ooxml/src/ui/src/teams/app-rail.css?raw
|
|
76
|
-
var app_rail_default = ":host {\n display: block;\n width: 5em;\n background: var(--office-teams-rail);\n border-inline-end: var(--office-border-width) solid var(--office-teams-divider);\n}\nul {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: var(--office-space-1);\n margin: 0;\n padding: var(--office-space-2) 0;\n list-style: none;\n}\nbutton {\n position: relative;\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: var(--office-space-0);\n width: 4.4em;\n padding: var(--office-space-2) 0;\n border: 0;\n border-radius: var(--office-radius-md);\n background: transparent;\n color: var(--office-teams-text-subtle);\n}\nbutton:hover {\n background: var(--office-selected);\n}\nbutton[aria-current='page'] {\n color: var(--office-teams-brand);\n font-weight: var(--office-font-weight-bold);\n}\nbutton[aria-current='page']::before {\n content: '';\n position: absolute;\n inset-inline-start: calc(-1 * var(--office-space-1));\n inset-block: 20%;\n width: var(--office-space-1);\n border-radius: var(--office-radius-full);\n background: var(--office-teams-brand);\n}\n.glyph {\n position: relative;\n display: grid;\n place-items: center;\n font-size: 1.3em;\n}\n.label {\n font-size: var(--office-font-size-2xs);\n}\n:host([hide-labels]) .label {\n display: none;\n}\n.badge {\n position: absolute;\n inset-block-start: -0.4em;\n inset-inline-end: -0.9em;\n min-width: 1.5em;\n padding: 0 var(--office-space-1);\n border-radius: var(--office-radius-full);\n background: var(--office-teams-brand);\n color: var(--office-teams-brand-foreground);\n font-size: var(--office-font-size-3xs);\n line-height: 1.6;\n text-align: center;\n}\n";
|
|
212
|
+
var app_rail_default = ":host {\n display: block;\n width: 5em;\n background: var(--office-teams-rail);\n border-inline-end: var(--office-border-width) solid var(--office-teams-divider);\n}\nul {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: var(--office-space-1);\n margin: 0;\n padding: var(--office-space-2) 0;\n list-style: none;\n}\nbutton {\n position: relative;\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: var(--office-space-0);\n width: 4.4em;\n padding: var(--office-space-2) 0;\n border: 0;\n border-radius: var(--office-radius-md);\n background: transparent;\n color: var(--office-teams-text-subtle);\n}\nbutton:hover {\n background: var(--office-selected);\n}\nbutton[aria-current='page'] {\n color: var(--office-teams-brand);\n font-weight: var(--office-font-weight-bold);\n}\nbutton[aria-current='page']::before {\n content: '';\n position: absolute;\n inset-inline-start: calc(-1 * var(--office-space-1));\n inset-block: 20%;\n width: var(--office-space-1);\n border-radius: var(--office-radius-full);\n background: var(--office-teams-brand);\n}\n.glyph {\n position: relative;\n display: grid;\n place-items: center;\n font-size: 1.3em;\n}\n.label {\n font-size: var(--office-font-size-2xs);\n}\n:host([hide-labels]) .label {\n display: none;\n}\n.badge {\n position: absolute;\n inset-block-start: -0.4em;\n inset-inline-end: -0.9em;\n min-width: 1.5em;\n padding: 0 var(--office-space-1);\n border-radius: var(--office-radius-full);\n background: var(--office-teams-brand);\n color: var(--office-teams-brand-foreground);\n font-size: var(--office-font-size-3xs);\n line-height: 1.6;\n text-align: center;\n}\n\n.short {\n display: none;\n}\n\n/* Compact shell: the rail becomes a bottom navigation bar with short labels. */\n@media (max-width: 56em) {\n :host {\n width: auto;\n padding-block-end: env(safe-area-inset-bottom, 0);\n padding-inline: env(safe-area-inset-left, 0) env(safe-area-inset-right, 0);\n border-inline-end: 0;\n border-block-start: var(--office-border-width) solid var(--office-teams-divider);\n }\n ul {\n flex-direction: row;\n justify-content: space-around;\n align-items: stretch;\n gap: 0;\n padding: var(--office-space-1) var(--office-space-1);\n }\n li {\n flex: 1 1 0;\n min-width: 0;\n }\n button {\n width: 100%;\n min-height: var(--office-touch-target, 44px);\n padding: var(--office-space-1) 0;\n justify-content: center;\n }\n button[aria-current='page']::before {\n inset-inline: 25%;\n inset-block: 0 auto;\n width: auto;\n height: var(--office-space-1);\n }\n .label.has-short {\n display: none;\n }\n .short {\n display: inline;\n font-size: var(--office-font-size-2xs);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n max-width: 100%;\n }\n}\n@media (max-width: 56em) and (max-height: 30em) {\n .label,\n .short {\n display: none;\n }\n button {\n min-height: 2.4em;\n }\n}\n\n/* The More sheet exists only on the phone bar. */\n.more-item {\n display: none;\n}\n.sheet {\n box-sizing: border-box;\n width: 100%;\n max-width: 100%;\n margin: auto 0 0;\n padding: var(--office-space-3) var(--office-space-3)\n calc(var(--office-space-3) + env(safe-area-inset-bottom, 0));\n border: 0;\n border-start-start-radius: var(--office-radius-lg);\n border-start-end-radius: var(--office-radius-lg);\n background: var(--office-popover);\n color: var(--office-foreground);\n box-shadow: var(--office-shadow-teams);\n}\n.sheet::backdrop {\n background: var(--office-overlay);\n}\n.sheet ul {\n flex-direction: column;\n align-items: stretch;\n padding: 0;\n}\n.sheet li {\n flex: none;\n}\n.sheet button {\n flex-direction: row;\n justify-content: flex-start;\n gap: var(--office-space-3);\n width: 100%;\n min-height: var(--office-touch-target, 44px);\n padding: var(--office-space-2) var(--office-space-3);\n font-size: var(--office-font-size);\n}\n.sheet button.close {\n justify-content: center;\n margin-top: var(--office-space-2);\n border: var(--office-border-width) solid var(--office-teams-divider);\n}\n.sheet .label {\n display: inline;\n font-size: var(--office-font-size);\n}\n@media (max-width: 56em) {\n li[data-secondary='true'] {\n display: none;\n }\n .more-item {\n display: block;\n flex: 1 1 0;\n min-width: 0;\n }\n .more .glyph {\n font-size: 1.3em;\n }\n}\n";
|
|
77
213
|
|
|
78
214
|
// src/teams/app-rail.ts
|
|
215
|
+
var total = (n) => n > 99 ? "99+" : String(n);
|
|
79
216
|
var OfficeUiAppRail = class extends TeamsElement {
|
|
80
217
|
static styles = withStyles(app_rail_default);
|
|
81
218
|
static properties = {
|
|
82
219
|
items: { attribute: false },
|
|
83
220
|
selected: { type: String },
|
|
84
|
-
hideLabels: { type: Boolean, attribute: "hide-labels", reflect: true }
|
|
221
|
+
hideLabels: { type: Boolean, attribute: "hide-labels", reflect: true },
|
|
222
|
+
moreOpen: { state: true }
|
|
85
223
|
};
|
|
86
224
|
constructor() {
|
|
87
225
|
super();
|
|
88
226
|
this.items = [];
|
|
89
227
|
this.selected = "";
|
|
90
228
|
this.hideLabels = false;
|
|
229
|
+
this.moreOpen = false;
|
|
91
230
|
}
|
|
92
231
|
connectedCallback() {
|
|
93
232
|
super.connectedCallback();
|
|
94
233
|
this.setAttribute("role", "navigation");
|
|
95
234
|
this.setAttribute("aria-label", "App bar");
|
|
96
235
|
}
|
|
236
|
+
updated(changed) {
|
|
237
|
+
const dialog = this.renderRoot.querySelector("dialog");
|
|
238
|
+
if (!dialog || !changed.has("moreOpen")) return;
|
|
239
|
+
if (this.moreOpen && !dialog.open) dialog.showModal();
|
|
240
|
+
else if (!this.moreOpen && dialog.open) dialog.close();
|
|
241
|
+
}
|
|
242
|
+
closeMore() {
|
|
243
|
+
this.moreOpen = false;
|
|
244
|
+
void this.updateComplete.then(
|
|
245
|
+
() => this.renderRoot.querySelector(".more")?.focus()
|
|
246
|
+
);
|
|
247
|
+
}
|
|
248
|
+
select(id) {
|
|
249
|
+
this.moreOpen = false;
|
|
250
|
+
this.fire("office-rail-select", { id });
|
|
251
|
+
}
|
|
97
252
|
render() {
|
|
253
|
+
const secondary = this.items.filter((i) => i.secondary);
|
|
254
|
+
const badge = secondary.reduce((n, i) => n + (i.badge ?? 0), 0);
|
|
255
|
+
const inMore = secondary.some((i) => i.id === this.selected);
|
|
98
256
|
return html`
|
|
99
257
|
<ul>
|
|
100
258
|
${this.items.map(
|
|
101
259
|
(item) => html`
|
|
102
|
-
<li>
|
|
103
|
-
<button
|
|
104
|
-
type="button"
|
|
105
|
-
aria-label=${item.label}
|
|
106
|
-
title=${item.label}
|
|
107
|
-
aria-current=${this.selected === item.id ? "page" : "false"}
|
|
108
|
-
@click=${() => this.fire("office-rail-select", { id: item.id })}
|
|
109
|
-
>
|
|
110
|
-
<span class="glyph">
|
|
111
|
-
${icon(item.icon)}
|
|
112
|
-
${item.badge ? html`<span class="badge">${item.badge > 99 ? "99+" : item.badge}</span>` : ""}
|
|
113
|
-
</span>
|
|
114
|
-
<span class="label">${item.label}</span>
|
|
115
|
-
</button>
|
|
116
|
-
</li>
|
|
260
|
+
<li data-secondary=${String(item.secondary === true)}>${this.button(item)}</li>
|
|
117
261
|
`
|
|
118
262
|
)}
|
|
263
|
+
${secondary.length ? html`<li class="more-item">
|
|
264
|
+
<button
|
|
265
|
+
type="button"
|
|
266
|
+
class="more"
|
|
267
|
+
aria-label=${badge ? `More, ${badge} unread` : "More"}
|
|
268
|
+
aria-haspopup="dialog"
|
|
269
|
+
aria-expanded=${String(this.moreOpen)}
|
|
270
|
+
aria-current=${inMore ? "page" : "false"}
|
|
271
|
+
@click=${() => this.moreOpen = true}
|
|
272
|
+
>
|
|
273
|
+
<span class="glyph">
|
|
274
|
+
${icon("more")}
|
|
275
|
+
${badge ? html`<span class="badge">${total(badge)}</span>` : nothing}
|
|
276
|
+
</span>
|
|
277
|
+
<span class="short" aria-hidden="true">More</span>
|
|
278
|
+
</button>
|
|
279
|
+
</li>` : nothing}
|
|
119
280
|
</ul>
|
|
281
|
+
${secondary.length ? html`<dialog
|
|
282
|
+
class="sheet"
|
|
283
|
+
aria-label="More apps"
|
|
284
|
+
@cancel=${(e) => {
|
|
285
|
+
e.preventDefault();
|
|
286
|
+
this.closeMore();
|
|
287
|
+
}}
|
|
288
|
+
@click=${(e) => {
|
|
289
|
+
if (e.target === e.currentTarget) this.closeMore();
|
|
290
|
+
}}
|
|
291
|
+
>
|
|
292
|
+
<ul>
|
|
293
|
+
${secondary.map((item) => html`<li>${this.button(item, true)}</li>`)}
|
|
294
|
+
</ul>
|
|
295
|
+
<button type="button" class="close" @click=${() => this.closeMore()}>Close</button>
|
|
296
|
+
</dialog>` : nothing}
|
|
120
297
|
`;
|
|
121
298
|
}
|
|
299
|
+
button(item, sheet = false) {
|
|
300
|
+
return html`<button
|
|
301
|
+
type="button"
|
|
302
|
+
aria-label=${item.label}
|
|
303
|
+
title=${item.label}
|
|
304
|
+
aria-current=${this.selected === item.id ? "page" : "false"}
|
|
305
|
+
@click=${() => this.select(item.id)}
|
|
306
|
+
>
|
|
307
|
+
<span class="glyph">
|
|
308
|
+
${icon(item.icon)}
|
|
309
|
+
${item.badge ? html`<span class="badge">${total(item.badge)}</span>` : nothing}
|
|
310
|
+
</span>
|
|
311
|
+
<span class=${item.shortLabel && !sheet ? "label has-short" : "label"}>${item.label}</span>
|
|
312
|
+
${item.shortLabel && !sheet ? html`<span class="short" aria-hidden="true">${item.shortLabel}</span>` : nothing}
|
|
313
|
+
</button>`;
|
|
314
|
+
}
|
|
122
315
|
};
|
|
123
316
|
var defineAppRail = definer("office-ui-app-rail", () => OfficeUiAppRail);
|
|
124
317
|
|
|
125
318
|
// raw-css:/home/runner/work/ooxml/ooxml/src/ui/src/teams/avatar.css?raw
|
|
126
|
-
var avatar_default = ":host {\n --_size: 2.3em;\n position: relative;\n display: inline-block;\n width: var(--_size);\n height: var(--_size);\n flex: none;\n}\n:host([size='sm']) {\n --_size: 1.7em;\n}\n:host([size='lg']) {\n --_size: 3em;\n}\n:host([size='xl']) {\n --_size: 6em;\n}\n\n.face {\n display: grid;\n place-items: center;\n width: 100%;\n height: 100%;\n border-radius: var(--office-radius-full);\n color: var(--office-call-foreground);\n font-size: calc(var(--_size) * 0.38);\n font-weight: var(--office-font-weight-bold);\n user-select: none;\n}\n\n.presence {\n position: absolute;\n inset-inline-end: 0;\n inset-block-end: 0;\n width: 32%;\n height: 32%;\n min-width: 0.5em;\n min-height: 0.5em;\n border-radius: var(--office-radius-full);\n border: var(--office-border-width-thick) solid var(--office-background);\n background: var(--office-presence-offline);\n}\n.presence[data-presence='available'] {\n background: var(--office-presence-available);\n}\n.presence[data-presence='busy'] {\n background: var(--office-presence-busy);\n}\n.presence[data-presence='away'] {\n background: var(--office-presence-away);\n}\n";
|
|
319
|
+
var avatar_default = ":host {\n --_size: 2.3em;\n position: relative;\n display: inline-block;\n width: var(--_size);\n height: var(--_size);\n flex: none;\n}\n:host([size='sm']) {\n --_size: 1.7em;\n}\n:host([size='lg']) {\n --_size: 3em;\n}\n:host([size='xl']) {\n --_size: 6em;\n}\n\n.face {\n display: grid;\n place-items: center;\n width: 100%;\n height: 100%;\n border-radius: var(--office-radius-full);\n color: var(--office-call-foreground);\n font-size: calc(var(--_size) * 0.38);\n font-weight: var(--office-font-weight-bold);\n user-select: none;\n}\n\n.presence {\n position: absolute;\n inset-inline-end: 0;\n inset-block-end: 0;\n width: 32%;\n height: 32%;\n min-width: 0.5em;\n min-height: 0.5em;\n border-radius: var(--office-radius-full);\n border: var(--office-border-width-thick) solid var(--office-background);\n background: var(--office-presence-offline);\n}\n.presence[data-presence='available'] {\n background: var(--office-presence-available);\n}\n.presence[data-presence='busy'] {\n background: var(--office-presence-busy);\n}\n.presence[data-presence='away'] {\n background: var(--office-presence-away);\n}\n.presence[data-presence='dnd'] {\n background: var(--office-presence-busy);\n}\n.presence[data-presence='brb'] {\n background: var(--office-presence-away);\n}\n/* Do not disturb carries a white bar; Away and Be right back share the clock hands. */\n.presence[data-presence='dnd']::after,\n.presence[data-presence='away']::after,\n.presence[data-presence='brb']::after {\n content: '';\n position: absolute;\n inset: 0;\n margin: auto;\n background: var(--office-background);\n}\n.presence[data-presence='dnd']::after {\n width: 60%;\n height: 16%;\n border-radius: var(--office-radius-full);\n}\n.presence[data-presence='away']::after,\n.presence[data-presence='brb']::after {\n width: 14%;\n height: 50%;\n inset-block: 10% auto;\n border-radius: var(--office-radius-full);\n}\n/* Appear offline is a hollow grey ring. */\n.presence[data-presence='offline'] {\n background: var(--office-background);\n border-color: var(--office-presence-offline);\n box-shadow: inset 0 0 0 var(--office-border-width-thick) var(--office-presence-offline);\n}\n";
|
|
127
320
|
|
|
128
321
|
// src/teams/avatar.ts
|
|
129
322
|
var PRESENCE_LABEL = {
|
|
130
323
|
available: "Available",
|
|
131
324
|
busy: "Busy",
|
|
325
|
+
dnd: "Do not disturb",
|
|
326
|
+
brb: "Be right back",
|
|
132
327
|
away: "Away",
|
|
133
328
|
offline: "Offline"
|
|
134
329
|
};
|
|
@@ -175,10 +370,10 @@ var call_controls_default = ":host {\n display: flex;\n align-items: center;\n j
|
|
|
175
370
|
|
|
176
371
|
// src/teams/call-controls.ts
|
|
177
372
|
var formatElapsed = (ms) => {
|
|
178
|
-
const
|
|
373
|
+
const total2 = Math.max(0, Math.floor(ms / 1e3));
|
|
179
374
|
const pad = (n) => String(n).padStart(2, "0");
|
|
180
|
-
const h = Math.floor(
|
|
181
|
-
return `${h ? `${h}:` : ""}${pad(Math.floor(
|
|
375
|
+
const h = Math.floor(total2 / 3600);
|
|
376
|
+
return `${h ? `${h}:` : ""}${pad(Math.floor(total2 % 3600 / 60))}:${pad(total2 % 60)}`;
|
|
182
377
|
};
|
|
183
378
|
var OfficeUiCallControls = class extends TeamsElement {
|
|
184
379
|
static styles = withStyles(call_controls_default);
|
|
@@ -262,6 +457,346 @@ var OfficeUiCallControls = class extends TeamsElement {
|
|
|
262
457
|
};
|
|
263
458
|
var defineCallControls = definer("office-ui-call-controls", () => OfficeUiCallControls);
|
|
264
459
|
|
|
460
|
+
// raw-css:/home/runner/work/ooxml/ooxml/src/ui/src/teams/calendar-agenda.css?raw
|
|
461
|
+
var calendar_agenda_default = ":host {\n display: block;\n overflow: auto;\n}\nheader {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: var(--office-space-3) var(--office-space-3) var(--office-space-2) var(--office-space-4);\n}\nh2 {\n margin: 0;\n font-size: var(--office-font-size-lg);\n}\nh3 {\n margin: var(--office-space-3) var(--office-space-4) var(--office-space-1);\n color: var(--office-teams-text-subtle);\n font-size: var(--office-font-size-sm);\n font-weight: var(--office-font-weight-bold);\n}\n.new {\n display: grid;\n place-items: center;\n width: 2.2em;\n height: 2.2em;\n border: 0;\n border-radius: var(--office-radius-md);\n background: transparent;\n color: var(--office-teams-brand);\n cursor: pointer;\n}\n.new:hover {\n background: var(--office-selected);\n}\n.empty {\n margin: var(--office-space-4);\n color: var(--office-teams-text-subtle);\n}\nul {\n display: grid;\n gap: var(--office-space-1);\n margin: 0;\n padding: 0 var(--office-space-2);\n list-style: none;\n}\nli {\n display: flex;\n align-items: center;\n gap: var(--office-space-2);\n}\n.row {\n display: grid;\n flex: 1;\n min-width: 0;\n padding: var(--office-space-2) var(--office-space-3);\n border: 0;\n border-inline-start: var(--office-border-width-thick) solid var(--office-teams-brand);\n border-radius: var(--office-radius);\n background: var(--office-teams-bubble);\n color: inherit;\n font: inherit;\n text-align: start;\n cursor: pointer;\n}\n.row:hover {\n background: var(--office-selected);\n}\n.row[data-live='true'] {\n border-inline-start-color: var(--office-call-live);\n}\n.time,\n.who {\n color: var(--office-teams-text-subtle);\n font-size: var(--office-font-size-xs);\n}\n.title {\n overflow: hidden;\n font-weight: var(--office-font-weight-bold);\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.join {\n padding: var(--office-space-2) var(--office-space-3);\n border: 0;\n border-radius: var(--office-radius-md);\n background: var(--office-teams-brand);\n color: var(--office-teams-brand-foreground);\n font: inherit;\n cursor: pointer;\n}\n.join:hover {\n background: var(--office-teams-brand-hover);\n}\n@media (pointer: coarse) {\n .new,\n .row,\n .join {\n min-width: var(--office-touch-target, 44px);\n min-height: var(--office-touch-target, 44px);\n }\n}\n";
|
|
462
|
+
|
|
463
|
+
// src/teams/calendar-agenda.ts
|
|
464
|
+
var HORIZON_DAYS = 14;
|
|
465
|
+
var JOIN_WINDOW_MS = 15 * 6e4;
|
|
466
|
+
var OfficeUiCalendarAgenda = class extends TeamsElement {
|
|
467
|
+
static styles = withStyles(calendar_agenda_default);
|
|
468
|
+
static properties = {
|
|
469
|
+
meetings: { attribute: false },
|
|
470
|
+
zone: { type: String },
|
|
471
|
+
now: { type: Number }
|
|
472
|
+
};
|
|
473
|
+
constructor() {
|
|
474
|
+
super();
|
|
475
|
+
this.meetings = [];
|
|
476
|
+
this.zone = localZone();
|
|
477
|
+
this.now = 0;
|
|
478
|
+
}
|
|
479
|
+
render() {
|
|
480
|
+
const now = this.now || Date.now();
|
|
481
|
+
const from = startOfDay(now, this.zone);
|
|
482
|
+
const rows = this.meetings.flatMap(
|
|
483
|
+
(m) => occurrencesBetween(m, from, from + HORIZON_DAYS * DAY_MS$1).map((o) => ({ o, m }))
|
|
484
|
+
).filter(({ o }) => o.end > now).sort((a, b) => a.o.start - b.o.start);
|
|
485
|
+
const groups = /* @__PURE__ */ new Map();
|
|
486
|
+
for (const row of rows) {
|
|
487
|
+
const key = dayKey(row.o.start, this.zone);
|
|
488
|
+
let group = groups.get(key);
|
|
489
|
+
if (!group) {
|
|
490
|
+
const label = new Intl.DateTimeFormat([], {
|
|
491
|
+
weekday: "long",
|
|
492
|
+
month: "short",
|
|
493
|
+
day: "numeric",
|
|
494
|
+
timeZone: this.zone
|
|
495
|
+
}).format(row.o.start);
|
|
496
|
+
groups.set(
|
|
497
|
+
key,
|
|
498
|
+
group = { label: key === dayKey(now, this.zone) ? `Today, ${label}` : label, rows: [] }
|
|
499
|
+
);
|
|
500
|
+
}
|
|
501
|
+
group.rows.push(row);
|
|
502
|
+
}
|
|
503
|
+
return html`
|
|
504
|
+
<header>
|
|
505
|
+
<h2>Calendar</h2>
|
|
506
|
+
<button
|
|
507
|
+
class="new"
|
|
508
|
+
type="button"
|
|
509
|
+
title="New meeting"
|
|
510
|
+
aria-label="New meeting"
|
|
511
|
+
@click=${() => this.fire("office-agenda-new", {})}
|
|
512
|
+
>
|
|
513
|
+
${icon("plus")}
|
|
514
|
+
</button>
|
|
515
|
+
</header>
|
|
516
|
+
${groups.size === 0 ? html`<p class="empty">No upcoming meetings. Schedule one with the plus button.</p>` : [...groups.values()].map(
|
|
517
|
+
(g) => html`<section>
|
|
518
|
+
<h3>${g.label}</h3>
|
|
519
|
+
<ul>
|
|
520
|
+
${g.rows.map(({ o, m }) => this.row(o, m, now))}
|
|
521
|
+
</ul>
|
|
522
|
+
</section>`
|
|
523
|
+
)}
|
|
524
|
+
`;
|
|
525
|
+
}
|
|
526
|
+
row(o, m, now) {
|
|
527
|
+
const title = o.title ?? m.title;
|
|
528
|
+
const time = `${this.clock(o.start)} - ${this.clock(o.end)}`;
|
|
529
|
+
const joinable = m.live || o.start - now <= JOIN_WINDOW_MS && o.end > now;
|
|
530
|
+
return html`<li>
|
|
531
|
+
<button
|
|
532
|
+
type="button"
|
|
533
|
+
class="row"
|
|
534
|
+
data-live=${String(m.live)}
|
|
535
|
+
aria-label=${`${title}, ${time}`}
|
|
536
|
+
@click=${() => this.fire("office-agenda-open", { meetingId: m.id, start: o.start })}
|
|
537
|
+
>
|
|
538
|
+
<span class="time">${time}</span>
|
|
539
|
+
<span class="title">${title}</span>
|
|
540
|
+
<span class="who">${m.mine ? "You organized" : m.organizerName}</span>
|
|
541
|
+
</button>
|
|
542
|
+
${joinable ? html`<button
|
|
543
|
+
type="button"
|
|
544
|
+
class="join"
|
|
545
|
+
aria-label=${`Join ${title}`}
|
|
546
|
+
@click=${() => this.fire("office-agenda-join", { meetingId: m.id })}
|
|
547
|
+
>
|
|
548
|
+
${m.live ? "Join now" : "Join"}
|
|
549
|
+
</button>` : ""}
|
|
550
|
+
</li>`;
|
|
551
|
+
}
|
|
552
|
+
clock(ms) {
|
|
553
|
+
return new Date(ms).toLocaleTimeString([], {
|
|
554
|
+
hour: "numeric",
|
|
555
|
+
minute: "2-digit",
|
|
556
|
+
timeZone: this.zone
|
|
557
|
+
});
|
|
558
|
+
}
|
|
559
|
+
};
|
|
560
|
+
var defineCalendarAgenda = definer(
|
|
561
|
+
"office-ui-calendar-agenda",
|
|
562
|
+
() => OfficeUiCalendarAgenda
|
|
563
|
+
);
|
|
564
|
+
|
|
565
|
+
// raw-css:/home/runner/work/ooxml/ooxml/src/ui/src/teams/calendar-view.css?raw
|
|
566
|
+
var calendar_view_default = ":host {\n --_hour: 4em;\n display: flex;\n flex-direction: column;\n min-height: 0;\n min-width: 0;\n background: var(--office-background);\n}\n.bar {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--office-space-2);\n padding: var(--office-space-3) var(--office-space-4);\n border-block-end: var(--office-border-width) solid var(--office-teams-divider);\n}\n.range {\n flex: 1 1 12em;\n margin: 0;\n font-size: var(--office-font-size-lg);\n}\nbutton {\n padding: var(--office-space-2) var(--office-space-3);\n border: var(--office-border-width) solid var(--office-teams-divider);\n border-radius: var(--office-radius-md);\n background: var(--office-background);\n color: inherit;\n font: inherit;\n cursor: pointer;\n}\nbutton:hover {\n background: var(--office-selected);\n}\n.step {\n display: grid;\n place-items: center;\n padding: var(--office-space-2);\n}\n.step.next .modes {\n display: inline-flex;\n border: var(--office-border-width) solid var(--office-teams-divider);\n border-radius: var(--office-radius-md);\n overflow: hidden;\n}\n.modes button {\n border: 0;\n border-radius: 0;\n}\n.modes button[aria-pressed='true'] {\n background: var(--office-teams-brand-subtle);\n color: var(--office-teams-brand);\n font-weight: var(--office-font-weight-bold);\n}\n.new {\n display: inline-flex;\n align-items: center;\n gap: var(--office-space-2);\n border-color: transparent;\n background: var(--office-teams-brand);\n color: var(--office-teams-brand-foreground);\n}\n.new:hover {\n background: var(--office-teams-brand-hover);\n}\n.step.next svg {\n transform: scaleX(-1);\n}\n\n.scroller {\n flex: 1;\n min-height: 0;\n overflow: auto;\n}\n.grid {\n display: grid;\n grid-template-columns: 4em repeat(var(--cols), minmax(0, 1fr));\n grid-template-rows: auto auto;\n min-width: 0;\n}\n.corner,\n.head {\n position: sticky;\n inset-block-start: 0;\n z-index: 3;\n background: var(--office-background);\n border-block-end: var(--office-border-width) solid var(--office-teams-divider);\n}\n.head {\n display: grid;\n justify-items: center;\n padding: var(--office-space-2) 0;\n border-inline-start: var(--office-border-width) solid var(--office-teams-divider);\n}\n.dow {\n color: var(--office-teams-text-subtle);\n font-size: var(--office-font-size-sm);\n}\n.dom {\n display: grid;\n place-items: center;\n min-width: 1.8em;\n height: 1.8em;\n border-radius: var(--office-radius-full);\n font-size: var(--office-font-size-lg);\n}\n.head[data-today='true'] .dom {\n background: var(--office-teams-brand);\n color: var(--office-teams-brand-foreground);\n}\n.hours {\n display: grid;\n grid-template-rows: repeat(24, var(--_hour));\n}\n.hours span {\n white-space: nowrap;\n padding-inline-end: var(--office-space-2);\n color: var(--office-teams-text-subtle);\n font-size: var(--office-font-size-xs);\n text-align: end;\n transform: translateY(-0.6em);\n}\n.column {\n position: relative;\n height: calc(24 * var(--_hour));\n border-inline-start: var(--office-border-width) solid var(--office-teams-divider);\n background-image: linear-gradient(\n to bottom,\n var(--office-teams-divider) var(--office-border-width),\n transparent var(--office-border-width)\n );\n background-size: 100% var(--_hour);\n}\n.column[data-today='true'] {\n background-color: var(--office-teams-brand-subtle);\n}\n.event {\n position: absolute;\n inset-block-start: calc(var(--top) * 1%);\n inset-inline-start: calc(var(--col) / var(--span) * 100%);\n box-sizing: border-box;\n width: calc(100% / var(--span));\n height: calc(var(--height) * 1%);\n min-height: 1.6em;\n display: grid;\n align-content: start;\n padding: var(--office-space-1) var(--office-space-2);\n overflow: hidden;\n border: var(--office-border-width) solid var(--office-teams-brand);\n border-inline-start-width: var(--office-border-width-thick);\n border-radius: var(--office-radius);\n background: var(--office-popover);\n text-align: start;\n z-index: 1;\n}\n.event[data-mine='true'] {\n background: var(--office-teams-bubble-own);\n}\n.event[data-live='true'] {\n border-color: var(--office-call-live);\n}\n.event-title {\n overflow: hidden;\n font-weight: var(--office-font-weight-bold);\n font-size: var(--office-font-size-sm);\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.event[data-short='true'] {\n align-content: center;\n}\n.event[data-short='true'] .event-time {\n display: none;\n}\n.event-time {\n overflow: hidden;\n color: var(--office-teams-text-subtle);\n font-size: var(--office-font-size-xs);\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.now {\n position: absolute;\n inset-block-start: calc(var(--top) * 1%);\n inset-inline: 0;\n z-index: 2;\n height: var(--office-border-width-thick);\n background: var(--office-danger);\n pointer-events: none;\n}\n.now::before {\n content: '';\n position: absolute;\n inset-inline-start: calc(-1 * var(--office-space-1));\n inset-block-start: calc(-1 * var(--office-space-1));\n width: var(--office-space-2);\n height: var(--office-space-2);\n border-radius: var(--office-radius-full);\n background: var(--office-danger);\n}\n@media (max-width: 40em) {\n :host {\n --_hour: 4em;\n }\n .grid {\n grid-template-columns: 3.8em repeat(var(--cols), minmax(0, 1fr));\n }\n .bar button {\n min-height: 2.75em;\n }\n .modes button {\n padding-inline: var(--office-space-2);\n }\n}\n";
|
|
567
|
+
|
|
568
|
+
// src/teams/calendar-view.ts
|
|
569
|
+
var MODES = [
|
|
570
|
+
{ id: "workweek", label: "Work week" },
|
|
571
|
+
{ id: "week", label: "Week" },
|
|
572
|
+
{ id: "day", label: "Day" }
|
|
573
|
+
];
|
|
574
|
+
var SLOT_MINUTES = 30;
|
|
575
|
+
var FIRST_VISIBLE_HOUR = 8;
|
|
576
|
+
var OfficeUiCalendarView = class extends TeamsElement {
|
|
577
|
+
static styles = withStyles(calendar_view_default);
|
|
578
|
+
static properties = {
|
|
579
|
+
meetings: { attribute: false },
|
|
580
|
+
zone: { type: String },
|
|
581
|
+
now: { type: Number },
|
|
582
|
+
mode: { type: String, reflect: true },
|
|
583
|
+
anchor: { state: true },
|
|
584
|
+
tick: { state: true }
|
|
585
|
+
};
|
|
586
|
+
timer;
|
|
587
|
+
scrolled = false;
|
|
588
|
+
resize;
|
|
589
|
+
constructor() {
|
|
590
|
+
super();
|
|
591
|
+
this.meetings = [];
|
|
592
|
+
this.zone = localZone();
|
|
593
|
+
this.now = 0;
|
|
594
|
+
this.mode = "workweek";
|
|
595
|
+
this.anchor = 0;
|
|
596
|
+
this.tick = 0;
|
|
597
|
+
}
|
|
598
|
+
clock() {
|
|
599
|
+
return this.now || Date.now();
|
|
600
|
+
}
|
|
601
|
+
connectedCallback() {
|
|
602
|
+
super.connectedCallback();
|
|
603
|
+
this.setAttribute("role", "region");
|
|
604
|
+
this.setAttribute("aria-label", "Calendar");
|
|
605
|
+
if (!this.anchor) this.anchor = this.clock();
|
|
606
|
+
if (globalThis.matchMedia?.("(max-width: 40em)").matches && this.mode === "workweek")
|
|
607
|
+
this.mode = "day";
|
|
608
|
+
this.timer = setInterval(() => this.tick = this.clock(), 6e4);
|
|
609
|
+
if (typeof ResizeObserver !== "undefined") {
|
|
610
|
+
this.resize = new ResizeObserver(() => this.scrollToWorkday());
|
|
611
|
+
this.resize.observe(this);
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
disconnectedCallback() {
|
|
615
|
+
clearInterval(this.timer);
|
|
616
|
+
this.resize?.disconnect();
|
|
617
|
+
super.disconnectedCallback();
|
|
618
|
+
}
|
|
619
|
+
updated() {
|
|
620
|
+
this.scrollToWorkday();
|
|
621
|
+
}
|
|
622
|
+
/** Start the day at 8:00, once the grid has a size. */
|
|
623
|
+
scrollToWorkday() {
|
|
624
|
+
const scroller = this.renderRoot.querySelector(".scroller");
|
|
625
|
+
if (this.scrolled || !scroller || scroller.clientHeight === 0) return;
|
|
626
|
+
scroller.scrollTop = scroller.scrollHeight / 24 * FIRST_VISIBLE_HOUR;
|
|
627
|
+
this.scrolled = true;
|
|
628
|
+
}
|
|
629
|
+
willUpdate(changed) {
|
|
630
|
+
if (changed.has("now") && this.now && changed.get("now") === 0) this.anchor = this.now;
|
|
631
|
+
}
|
|
632
|
+
setMode(mode) {
|
|
633
|
+
this.mode = mode;
|
|
634
|
+
this.fire("office-calendar-mode", { mode });
|
|
635
|
+
}
|
|
636
|
+
range(days) {
|
|
637
|
+
const first = days[0];
|
|
638
|
+
const last = days[days.length - 1];
|
|
639
|
+
const fmt = (opts, ms) => new Intl.DateTimeFormat([], { ...opts, timeZone: this.zone }).format(ms);
|
|
640
|
+
if (days.length === 1)
|
|
641
|
+
return fmt({ weekday: "long", month: "long", day: "numeric", year: "numeric" }, first.start);
|
|
642
|
+
return new Intl.DateTimeFormat([], {
|
|
643
|
+
month: "long",
|
|
644
|
+
day: "numeric",
|
|
645
|
+
year: "numeric",
|
|
646
|
+
timeZone: this.zone
|
|
647
|
+
}).formatRange(first.start, last.start);
|
|
648
|
+
}
|
|
649
|
+
newAt(day, event) {
|
|
650
|
+
const column = event.currentTarget;
|
|
651
|
+
const box = column.getBoundingClientRect();
|
|
652
|
+
const fraction = box.height ? (event.clientY - box.top) / box.height : 0;
|
|
653
|
+
const minute = Math.floor(Math.max(0, fraction) * 1440 / SLOT_MINUTES) * SLOT_MINUTES;
|
|
654
|
+
const start = zonedToUtc(
|
|
655
|
+
{ year: day.year, month: day.month, day: day.day, hour: 0, minute },
|
|
656
|
+
this.zone
|
|
657
|
+
);
|
|
658
|
+
this.fire("office-calendar-new", { start });
|
|
659
|
+
}
|
|
660
|
+
render() {
|
|
661
|
+
const now = this.clock();
|
|
662
|
+
const days = viewDays(this.anchor || now, this.mode, this.zone);
|
|
663
|
+
const todayStart = startOfDay(now, this.zone);
|
|
664
|
+
const nowParts = zonedParts(now, this.zone);
|
|
665
|
+
return html`
|
|
666
|
+
<div class="bar">
|
|
667
|
+
<h2 class="range" aria-live="polite">${this.range(days)}</h2>
|
|
668
|
+
<button type="button" class="today" @click=${() => this.anchor = this.clock()}>
|
|
669
|
+
Today
|
|
670
|
+
</button>
|
|
671
|
+
<button
|
|
672
|
+
type="button"
|
|
673
|
+
class="step"
|
|
674
|
+
aria-label=${this.mode === "day" ? "Previous day" : "Previous week"}
|
|
675
|
+
@click=${() => this.anchor = shiftAnchor(this.anchor || now, this.mode, -1, this.zone)}
|
|
676
|
+
>
|
|
677
|
+
${icon("back")}
|
|
678
|
+
</button>
|
|
679
|
+
<button
|
|
680
|
+
type="button"
|
|
681
|
+
class="step next"
|
|
682
|
+
aria-label=${this.mode === "day" ? "Next day" : "Next week"}
|
|
683
|
+
@click=${() => this.anchor = shiftAnchor(this.anchor || now, this.mode, 1, this.zone)}
|
|
684
|
+
>
|
|
685
|
+
${icon("back")}
|
|
686
|
+
</button>
|
|
687
|
+
<div class="modes" role="group" aria-label="Calendar view">
|
|
688
|
+
${MODES.map(
|
|
689
|
+
(m) => html`<button
|
|
690
|
+
type="button"
|
|
691
|
+
aria-pressed=${String(this.mode === m.id)}
|
|
692
|
+
@click=${() => this.setMode(m.id)}
|
|
693
|
+
>
|
|
694
|
+
${m.label}
|
|
695
|
+
</button>`
|
|
696
|
+
)}
|
|
697
|
+
</div>
|
|
698
|
+
<button
|
|
699
|
+
type="button"
|
|
700
|
+
class="new"
|
|
701
|
+
@click=${() => this.fire("office-calendar-new", { start: 0 })}
|
|
702
|
+
>
|
|
703
|
+
${icon("plus")} New meeting
|
|
704
|
+
</button>
|
|
705
|
+
</div>
|
|
706
|
+
<div class="scroller">
|
|
707
|
+
<div class="grid" style=${`--cols:${days.length}`}>
|
|
708
|
+
<div class="corner"></div>
|
|
709
|
+
${days.map((d) => this.dayHead(d, d.start === todayStart))}
|
|
710
|
+
<div class="hours" aria-hidden="true">
|
|
711
|
+
${Array.from({ length: 24 }, (_, h) => html`<span>${this.hourLabel(h)}</span>`)}
|
|
712
|
+
</div>
|
|
713
|
+
${days.map((d) => this.column(d, d.start === todayStart, nowParts.hour * 60 + nowParts.minute))}
|
|
714
|
+
</div>
|
|
715
|
+
</div>
|
|
716
|
+
`;
|
|
717
|
+
}
|
|
718
|
+
hourLabel(hour) {
|
|
719
|
+
if (hour === 0) return "";
|
|
720
|
+
return new Date(Date.UTC(2e3, 0, 1, hour)).toLocaleTimeString([], {
|
|
721
|
+
hour: "numeric",
|
|
722
|
+
timeZone: "UTC"
|
|
723
|
+
});
|
|
724
|
+
}
|
|
725
|
+
dayHead(day, today) {
|
|
726
|
+
const name = new Intl.DateTimeFormat([], { weekday: "short", timeZone: this.zone }).format(
|
|
727
|
+
day.start
|
|
728
|
+
);
|
|
729
|
+
return html`<div class="head" data-today=${String(today)}>
|
|
730
|
+
<span class="dow">${name}</span>
|
|
731
|
+
<span class="dom">${day.day}</span>
|
|
732
|
+
</div>`;
|
|
733
|
+
}
|
|
734
|
+
column(day, today, nowMinute) {
|
|
735
|
+
const occurrences = this.meetings.flatMap(
|
|
736
|
+
(m) => occurrencesBetween(m, day.start, day.end).map((o) => ({ o, m }))
|
|
737
|
+
);
|
|
738
|
+
const placed = layoutDay(
|
|
739
|
+
occurrences.map((x) => x.o),
|
|
740
|
+
day,
|
|
741
|
+
this.zone
|
|
742
|
+
);
|
|
743
|
+
const byKey = new Map(occurrences.map((x) => [x.o.key, x.m]));
|
|
744
|
+
const label = new Intl.DateTimeFormat([], {
|
|
745
|
+
weekday: "long",
|
|
746
|
+
month: "long",
|
|
747
|
+
day: "numeric",
|
|
748
|
+
timeZone: this.zone
|
|
749
|
+
}).format(day.start);
|
|
750
|
+
return html`<div
|
|
751
|
+
class="column"
|
|
752
|
+
role="group"
|
|
753
|
+
aria-label=${label}
|
|
754
|
+
data-today=${String(today)}
|
|
755
|
+
@click=${(e) => {
|
|
756
|
+
if (e.target === e.currentTarget) this.newAt(day, e);
|
|
757
|
+
}}
|
|
758
|
+
>
|
|
759
|
+
${placed.map((p) => {
|
|
760
|
+
const meeting = byKey.get(p.occurrence.key);
|
|
761
|
+
const title = p.occurrence.title ?? meeting.title;
|
|
762
|
+
const time = `${this.clockText(p.occurrence.start)} - ${this.clockText(p.occurrence.end)}`;
|
|
763
|
+
return html`<button
|
|
764
|
+
type="button"
|
|
765
|
+
class="event"
|
|
766
|
+
data-live=${String(meeting.live)}
|
|
767
|
+
data-mine=${String(meeting.mine)}
|
|
768
|
+
data-short=${String(p.endMinute - p.startMinute <= 30)}
|
|
769
|
+
aria-label=${`${title}, ${time}`}
|
|
770
|
+
style=${`--top:${p.startMinute / 1440 * 100};--height:${(p.endMinute - p.startMinute) / 1440 * 100};--col:${p.column};--span:${p.columns}`}
|
|
771
|
+
@click=${(e) => {
|
|
772
|
+
e.stopPropagation();
|
|
773
|
+
this.fire("office-calendar-open", {
|
|
774
|
+
meetingId: meeting.id,
|
|
775
|
+
start: p.occurrence.start
|
|
776
|
+
});
|
|
777
|
+
}}
|
|
778
|
+
>
|
|
779
|
+
<span class="event-title">${title}</span>
|
|
780
|
+
<span class="event-time">${time}</span>
|
|
781
|
+
</button>`;
|
|
782
|
+
})}
|
|
783
|
+
${today ? html`<span
|
|
784
|
+
class="now"
|
|
785
|
+
style=${`--top:${nowMinute / 1440 * 100}`}
|
|
786
|
+
aria-hidden="true"
|
|
787
|
+
></span>` : nothing}
|
|
788
|
+
</div>`;
|
|
789
|
+
}
|
|
790
|
+
clockText(ms) {
|
|
791
|
+
return new Date(ms).toLocaleTimeString([], {
|
|
792
|
+
hour: "numeric",
|
|
793
|
+
minute: "2-digit",
|
|
794
|
+
timeZone: this.zone
|
|
795
|
+
});
|
|
796
|
+
}
|
|
797
|
+
};
|
|
798
|
+
var defineCalendarView = definer("office-ui-calendar-view", () => OfficeUiCalendarView);
|
|
799
|
+
|
|
265
800
|
// raw-css:/home/runner/work/ooxml/ooxml/src/ui/src/teams/call-grid.css?raw
|
|
266
801
|
var call_grid_default = ":host {\n display: block;\n min-height: 0;\n background: var(--office-call-background);\n color: var(--office-call-foreground);\n}\n.empty {\n display: grid;\n place-items: center;\n height: 100%;\n margin: 0;\n color: var(--office-call-muted-foreground);\n}\n.grid {\n display: grid;\n gap: var(--office-space-2);\n height: 100%;\n padding: var(--office-space-2);\n grid-template-columns: repeat(var(--cols, 1), minmax(0, 1fr));\n grid-auto-rows: minmax(0, 1fr);\n}\n.grid[data-spotlight='true'] {\n grid-template-columns: minmax(0, 4fr) minmax(0, 1fr);\n grid-template-rows: repeat(var(--rows, 1), minmax(0, 1fr));\n}\n.grid[data-spotlight='true'] .tile[data-main='true'] {\n grid-row: 1 / span var(--rows, 1);\n}\n\n.tile {\n position: relative;\n display: grid;\n place-items: center;\n min-height: 6em;\n overflow: hidden;\n border-radius: var(--office-radius-lg);\n background: var(--office-call-tile);\n}\nvideo {\n position: absolute;\n inset: 0;\n width: 100%;\n height: 100%;\n object-fit: cover;\n background: var(--office-call-background);\n}\n.tile[data-screen='true'] video {\n object-fit: contain;\n}\n.tile[data-self='true'] video {\n transform: scaleX(-1);\n}\n.tile[data-self='true'][data-screen='true'] video {\n transform: none;\n}\n\n.name {\n position: absolute;\n inset-inline-start: var(--office-space-2);\n inset-block-end: var(--office-space-2);\n display: flex;\n align-items: center;\n gap: var(--office-space-1-5);\n max-width: calc(100% - 2 * var(--office-space-2));\n padding: var(--office-space-0) var(--office-space-2);\n border-radius: var(--office-radius-md);\n background: var(--office-call-scrim);\n font-size: var(--office-font-size-sm);\n}\n.name span:last-child {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.muted {\n display: grid;\n color: var(--office-call-danger);\n}\n.hand {\n position: absolute;\n inset-block-start: var(--office-space-2);\n inset-inline-end: var(--office-space-2);\n font-size: 1.5em;\n}\n.status {\n position: absolute;\n inset-block-start: var(--office-space-2);\n inset-inline-start: var(--office-space-2);\n padding: 0 var(--office-space-2);\n border-radius: var(--office-radius-md);\n background: var(--office-call-scrim);\n font-size: var(--office-font-size-xs);\n}\n";
|
|
267
802
|
|
|
@@ -329,7 +864,7 @@ var OfficeUiCallGrid = class extends TeamsElement {
|
|
|
329
864
|
var defineCallGrid = definer("office-ui-call-grid", () => OfficeUiCallGrid);
|
|
330
865
|
|
|
331
866
|
// raw-css:/home/runner/work/ooxml/ooxml/src/ui/src/teams/channel-list.css?raw
|
|
332
|
-
var channel_list_default = ":host {\n display: block;\n overflow: auto;\n}\n.team {\n display: flex;\n align-items: center;\n padding: var(--office-space-1) var(--office-space-2) var(--office-space-1) var(--office-space-1);\n}\n.toggle {\n display: flex;\n flex: 1;\n align-items: center;\n gap: var(--office-space-1);\n min-width: 0;\n padding: var(--office-space-2);\n border: 0;\n border-radius: var(--office-radius);\n background: transparent;\n font-weight: var(--office-font-weight-bold);\n text-align: start;\n}\n.toggle:hover,\n.add:hover {\n background: var(--office-selected);\n}\n.chevron {\n display: grid;\n transition: transform var(--office-duration-fast);\n}\n.chevron[data-open='true'] {\n transform: rotate(90deg);\n}\n.name {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.add {\n display: grid;\n place-items: center;\n width: 2em;\n height: 2em;\n border: 0;\n border-radius: var(--office-radius);\n background: transparent;\n color: var(--office-teams-text-subtle);\n}\nul {\n margin: 0;\n padding: 0 var(--office-space-2);\n list-style: none;\n}\nul[hidden] {\n display: none;\n}\n.row {\n position: relative;\n display: flex;\n align-items: center;\n gap: var(--office-space-2);\n width: 100%;\n padding: var(--office-space-2) var(--office-space-3) var(--office-space-2) var(--office-space-5);\n border: 0;\n border-radius: var(--office-radius);\n background: transparent;\n color: var(--office-teams-text-subtle);\n text-align: start;\n}\n.row:hover {\n background: var(--office-selected);\n}\n.row[aria-current='true'] {\n background: var(--office-teams-brand-subtle);\n color: var(--office-foreground);\n font-weight: var(--office-font-weight-bold);\n}\n.row[aria-current='true']::before {\n content: '';\n position: absolute;\n inset-inline-start: 0;\n inset-block: 20%;\n width: var(--office-space-1);\n border-radius: var(--office-radius-full);\n background: var(--office-teams-brand);\n}\n.row[data-unread='true'] {\n color: var(--office-foreground);\n font-weight: var(--office-font-weight-bold);\n}\n.title {\n flex: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.live {\n display: grid;\n color: var(--office-call-live);\n}\n.count {\n min-width: 1.6em;\n padding: 0 var(--office-space-1);\n border-radius: var(--office-radius-full);\n background: var(--office-teams-brand);\n color: var(--office-teams-brand-foreground);\n font-size: var(--office-font-size-xs);\n line-height: 1.6;\n text-align: center;\n}\n";
|
|
867
|
+
var channel_list_default = ":host {\n display: block;\n overflow: auto;\n}\n.team {\n display: flex;\n align-items: center;\n padding: var(--office-space-1) var(--office-space-2) var(--office-space-1) var(--office-space-1);\n}\n.toggle {\n display: flex;\n flex: 1;\n align-items: center;\n gap: var(--office-space-1);\n min-width: 0;\n padding: var(--office-space-2);\n border: 0;\n border-radius: var(--office-radius);\n background: transparent;\n font-weight: var(--office-font-weight-bold);\n text-align: start;\n}\n.toggle:hover,\n.add:hover {\n background: var(--office-selected);\n}\n.chevron {\n display: grid;\n transition: transform var(--office-duration-fast);\n}\n.chevron[data-open='true'] {\n transform: rotate(90deg);\n}\n.name {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.add {\n display: grid;\n place-items: center;\n width: 2em;\n height: 2em;\n border: 0;\n border-radius: var(--office-radius);\n background: transparent;\n color: var(--office-teams-text-subtle);\n}\nul {\n margin: 0;\n padding: 0 var(--office-space-2);\n list-style: none;\n}\nul[hidden] {\n display: none;\n}\n.row {\n position: relative;\n display: flex;\n align-items: center;\n gap: var(--office-space-2);\n width: 100%;\n padding: var(--office-space-2) var(--office-space-3) var(--office-space-2) var(--office-space-5);\n border: 0;\n border-radius: var(--office-radius);\n background: transparent;\n color: var(--office-teams-text-subtle);\n text-align: start;\n}\n.row:hover {\n background: var(--office-selected);\n}\n.row[aria-current='true'] {\n background: var(--office-teams-brand-subtle);\n color: var(--office-foreground);\n font-weight: var(--office-font-weight-bold);\n}\n.row[aria-current='true']::before {\n content: '';\n position: absolute;\n inset-inline-start: 0;\n inset-block: 20%;\n width: var(--office-space-1);\n border-radius: var(--office-radius-full);\n background: var(--office-teams-brand);\n}\n.row[data-unread='true'] {\n color: var(--office-foreground);\n font-weight: var(--office-font-weight-bold);\n}\n.title {\n flex: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.live {\n display: grid;\n color: var(--office-call-live);\n}\n.count {\n min-width: 1.6em;\n padding: 0 var(--office-space-1);\n border-radius: var(--office-radius-full);\n background: var(--office-teams-brand);\n color: var(--office-teams-brand-foreground);\n font-size: var(--office-font-size-xs);\n line-height: 1.6;\n text-align: center;\n}\n\n@media (pointer: coarse) {\n .toggle,\n .add,\n .row {\n min-width: var(--office-touch-target, 44px);\n min-height: var(--office-touch-target, 44px);\n }\n}\n";
|
|
333
868
|
|
|
334
869
|
// src/teams/channel-list.ts
|
|
335
870
|
var OfficeUiChannelList = class extends TeamsElement {
|
|
@@ -395,7 +930,7 @@ var OfficeUiChannelList = class extends TeamsElement {
|
|
|
395
930
|
var defineChannelList = definer("office-ui-channel-list", () => OfficeUiChannelList);
|
|
396
931
|
|
|
397
932
|
// raw-css:/home/runner/work/ooxml/ooxml/src/ui/src/teams/chat-composer.css?raw
|
|
398
|
-
var chat_composer_default = ":host {\n display: block;\n min-width: 0;\n flex: none;\n padding: 0 var(--office-space-5) var(--office-space-4);\n}\n.typing {\n min-height: 1.4em;\n color: var(--office-teams-text-subtle);\n font-size: var(--office-font-size-xs);\n}\n.box {\n position: relative;\n border: var(--office-border-width) solid var(--office-teams-divider);\n border-block-end: var(--office-border-width-thick) solid var(--office-teams-divider);\n border-radius: var(--office-radius-md);\n background: var(--office-field-background);\n}\n.box:focus-within {\n border-block-end-color: var(--office-teams-brand);\n}\n.banner {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: var(--office-space-1) var(--office-space-3);\n border-bottom: var(--office-border-width) solid var(--office-teams-divider);\n background: var(--office-teams-panel);\n font-size: var(--office-font-size-sm);\n}\ntextarea {\n display: block;\n width: 100%;\n min-height: 3.2em;\n max-height: 12em;\n padding: var(--office-space-3);\n border: 0;\n outline: 0;\n resize: none;\n background: transparent;\n color: inherit;\n font: inherit;\n overflow-y: auto;\n line-height: 1.5;\n}\n.bar {\n display: flex;\n align-items: center;\n gap: var(--office-space-1);\n padding: 0 var(--office-space-2) var(--office-space-2);\n}\n.spacer {\n flex: 1;\n}\n.bar button,\n.banner button,\n.pending button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: var(--office-space-1);\n min-width: 2.2em;\n height: 2.2em;\n border: 0;\n border-radius: var(--office-radius);\n background: transparent;\n color: var(--office-teams-text-subtle);\n}\n.bar button:hover:not(:disabled),\n.banner button:hover {\n background: var(--office-selected);\n color: var(--office-foreground);\n}\n.bar button:disabled {\n opacity: 0.45;\n cursor: not-allowed;\n}\n.bar .send:not(:disabled) {\n color: var(--office-teams-brand);\n}\n.pending {\n display: flex;\n flex-wrap: wrap;\n gap: var(--office-space-1);\n margin: 0;\n padding: 0 var(--office-space-3);\n list-style: none;\n}\n.pending button {\n padding: 0 var(--office-space-2);\n border: var(--office-border-width) solid var(--office-teams-divider);\n background: var(--office-teams-panel);\n font-size: var(--office-font-size-sm);\n color: var(--office-foreground);\n}\n.emoji {\n position: relative;\n}\n.picker {\n position: absolute;\n inset-block-end: calc(100% + var(--office-space-1));\n inset-inline-start: 0;\n z-index: 2;\n display: grid;\n grid-template-columns: repeat(5, 1fr);\n gap: var(--office-space-0);\n padding: var(--office-space-2);\n border: var(--office-border-width) solid var(--office-teams-divider);\n border-radius: var(--office-radius-md);\n background: var(--office-popover);\n box-shadow: var(--office-shadow-teams);\n}\n.picker button {\n font-size: 1.3em;\n}\n\ntextarea:focus-visible {\n outline: none;\n}\n.box:focus-within {\n border-color: var(--office-teams-brand);\n}\n.pending {\n max-height: 7em;\n overflow-y: auto;\n padding-block-end: var(--office-space-2);\n}\n.pending li {\n min-width: 0;\n max-width: 100%;\n}\n.pending button {\n max-width: 100%;\n height: auto;\n min-height: 2.4em;\n}\n.file-label {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n min-width: 0;\n}\n@media (max-width: 600px) {\n :host {\n padding: 0 var(--office-space-2) var(--office-space-2);\n }\n textarea {\n font-size: var(--office-font-size-touch);\n min-height: 3em;\n }\n .bar button {\n min-width: var(--office-touch-target);\n height: var(--office-touch-target);\n }\n}\n";
|
|
933
|
+
var chat_composer_default = ":host {\n display: block;\n min-width: 0;\n flex: none;\n padding: 0 var(--office-space-5) var(--office-space-4);\n}\n.typing {\n min-height: 1.4em;\n color: var(--office-teams-text-subtle);\n font-size: var(--office-font-size-xs);\n}\n.box {\n position: relative;\n border: var(--office-border-width) solid var(--office-teams-divider);\n border-block-end: var(--office-border-width-thick) solid var(--office-teams-divider);\n border-radius: var(--office-radius-md);\n background: var(--office-field-background);\n}\n.box:focus-within {\n border-block-end-color: var(--office-teams-brand);\n}\n.banner {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: var(--office-space-1) var(--office-space-3);\n border-bottom: var(--office-border-width) solid var(--office-teams-divider);\n background: var(--office-teams-panel);\n font-size: var(--office-font-size-sm);\n}\ntextarea {\n display: block;\n width: 100%;\n min-height: 3.2em;\n max-height: 12em;\n padding: var(--office-space-3);\n border: 0;\n outline: 0;\n resize: none;\n background: transparent;\n color: inherit;\n font: inherit;\n overflow-y: auto;\n line-height: 1.5;\n}\n.bar {\n display: flex;\n align-items: center;\n gap: var(--office-space-1);\n padding: 0 var(--office-space-2) var(--office-space-2);\n}\n.spacer {\n flex: 1;\n}\n.bar button,\n.banner button,\n.pending button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: var(--office-space-1);\n min-width: 2.2em;\n height: 2.2em;\n border: 0;\n border-radius: var(--office-radius);\n background: transparent;\n color: var(--office-teams-text-subtle);\n}\n.bar button:hover:not(:disabled),\n.banner button:hover {\n background: var(--office-selected);\n color: var(--office-foreground);\n}\n.bar button:disabled {\n opacity: 0.45;\n cursor: not-allowed;\n}\n.bar .send:not(:disabled) {\n color: var(--office-teams-brand);\n}\n.pending {\n display: flex;\n flex-wrap: wrap;\n gap: var(--office-space-1);\n margin: 0;\n padding: 0 var(--office-space-3);\n list-style: none;\n}\n.pending button {\n padding: 0 var(--office-space-2);\n border: var(--office-border-width) solid var(--office-teams-divider);\n background: var(--office-teams-panel);\n font-size: var(--office-font-size-sm);\n color: var(--office-foreground);\n}\n.emoji {\n position: relative;\n}\n.picker {\n position: absolute;\n inset-block-end: calc(100% + var(--office-space-1));\n inset-inline-start: 0;\n z-index: 2;\n display: grid;\n grid-template-columns: repeat(5, 1fr);\n gap: var(--office-space-0);\n padding: var(--office-space-2);\n border: var(--office-border-width) solid var(--office-teams-divider);\n border-radius: var(--office-radius-md);\n background: var(--office-popover);\n box-shadow: var(--office-shadow-teams);\n}\n.picker button {\n font-size: 1.3em;\n}\n\ntextarea:focus-visible {\n outline: none;\n}\n.box:focus-within {\n border-color: var(--office-teams-brand);\n}\n.pending {\n max-height: 7em;\n overflow-y: auto;\n padding-block-end: var(--office-space-2);\n}\n.pending li {\n min-width: 0;\n max-width: 100%;\n}\n.pending button {\n max-width: 100%;\n height: auto;\n min-height: 2.4em;\n}\n.file-label {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n min-width: 0;\n}\n@media (max-width: 600px) {\n :host {\n padding: 0 var(--office-space-2) var(--office-space-2);\n }\n textarea {\n font-size: var(--office-font-size-touch);\n min-height: 3em;\n }\n}\n@media (pointer: coarse) {\n .bar button,\n .banner button,\n .pending button,\n .picker button {\n min-width: var(--office-touch-target, 44px);\n min-height: var(--office-touch-target, 44px);\n }\n}\n\n/* The @ picker: a listbox of people above the compose box. */\n.mentions {\n position: absolute;\n inset-block-end: calc(100% + var(--office-space-1));\n inset-inline: 0;\n z-index: 3;\n max-height: 16em;\n margin: 0;\n padding: var(--office-space-1);\n overflow-y: auto;\n list-style: none;\n border: var(--office-border-width) solid var(--office-teams-divider);\n border-radius: var(--office-radius-md);\n background: var(--office-popover);\n box-shadow: var(--office-shadow-teams);\n}\n.mentions li {\n display: flex;\n align-items: center;\n gap: var(--office-space-3);\n min-height: 2.6em;\n padding: var(--office-space-1) var(--office-space-3);\n border-radius: var(--office-radius);\n cursor: pointer;\n}\n.mentions li[aria-selected='true'],\n.mentions li:hover {\n background: var(--office-selected);\n}\n.mentions .name {\n font-weight: 600;\n}\n.mentions .hint {\n margin-inline-start: auto;\n color: var(--office-teams-text-subtle);\n font-size: var(--office-font-size-xs);\n}\n.mentions .everyone {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 2em;\n height: 2em;\n border-radius: 50%;\n background: var(--office-teams-brand-subtle);\n color: var(--office-teams-brand);\n font-weight: 700;\n}\n@media (pointer: coarse) {\n .mentions li {\n min-height: var(--office-touch-target, 44px);\n }\n}\n";
|
|
399
934
|
var EMOJI = [
|
|
400
935
|
"\u{1F600}",
|
|
401
936
|
"\u{1F604}",
|
|
@@ -430,8 +965,12 @@ var OfficeUiChatComposer = class extends TeamsElement {
|
|
|
430
965
|
value: { type: String },
|
|
431
966
|
files: { state: true },
|
|
432
967
|
missingFiles: { attribute: false },
|
|
433
|
-
emojiOpen: { state: true }
|
|
968
|
+
emojiOpen: { state: true },
|
|
969
|
+
mentionTargets: { attribute: false },
|
|
970
|
+
picker: { state: true },
|
|
971
|
+
pickerIndex: { state: true }
|
|
434
972
|
};
|
|
973
|
+
inserted = [];
|
|
435
974
|
lastTyping = 0;
|
|
436
975
|
constructor() {
|
|
437
976
|
super();
|
|
@@ -444,6 +983,9 @@ var OfficeUiChatComposer = class extends TeamsElement {
|
|
|
444
983
|
this.files = [];
|
|
445
984
|
this.missingFiles = [];
|
|
446
985
|
this.emojiOpen = false;
|
|
986
|
+
this.mentionTargets = [];
|
|
987
|
+
this.picker = null;
|
|
988
|
+
this.pickerIndex = 0;
|
|
447
989
|
}
|
|
448
990
|
focusMessage() {
|
|
449
991
|
void this.updateComplete.then(
|
|
@@ -468,15 +1010,19 @@ var OfficeUiChatComposer = class extends TeamsElement {
|
|
|
468
1010
|
}
|
|
469
1011
|
submit() {
|
|
470
1012
|
if (!this.canSend) return;
|
|
471
|
-
const { value: text, files } = this;
|
|
1013
|
+
const { value: text, files, inserted: mentions } = this;
|
|
472
1014
|
this.value = "";
|
|
473
1015
|
this.files = [];
|
|
1016
|
+
this.inserted = [];
|
|
474
1017
|
this.emojiOpen = false;
|
|
475
|
-
this.
|
|
1018
|
+
this.picker = null;
|
|
1019
|
+
const detail = { text, files, ...mentions.length ? { mentions } : {} };
|
|
1020
|
+
this.fire("office-chat-send", detail);
|
|
476
1021
|
this.focusMessage();
|
|
477
1022
|
}
|
|
478
1023
|
onInput(event) {
|
|
479
1024
|
this.value = event.target.value;
|
|
1025
|
+
this.syncPicker();
|
|
480
1026
|
this.saveDraft();
|
|
481
1027
|
const now = Date.now();
|
|
482
1028
|
if (now - this.lastTyping > 2e3) {
|
|
@@ -484,7 +1030,51 @@ var OfficeUiChatComposer = class extends TeamsElement {
|
|
|
484
1030
|
this.fire("office-chat-typing", {});
|
|
485
1031
|
}
|
|
486
1032
|
}
|
|
1033
|
+
/** Open the picker while the caret sits in an `@query` that somebody matches. */
|
|
1034
|
+
syncPicker() {
|
|
1035
|
+
const area = this.renderRoot.querySelector("textarea");
|
|
1036
|
+
const query = area ? mentionQueryAt(this.value, area.selectionStart) : null;
|
|
1037
|
+
if (!query || filterMentionTargets(this.mentionTargets, query.query).length === 0) {
|
|
1038
|
+
this.picker = null;
|
|
1039
|
+
return;
|
|
1040
|
+
}
|
|
1041
|
+
if (this.picker?.start !== query.start || this.picker.query !== query.query)
|
|
1042
|
+
this.pickerIndex = 0;
|
|
1043
|
+
this.picker = query;
|
|
1044
|
+
}
|
|
1045
|
+
pickerOptions() {
|
|
1046
|
+
return this.picker ? filterMentionTargets(this.mentionTargets, this.picker.query) : [];
|
|
1047
|
+
}
|
|
1048
|
+
chooseMention(target) {
|
|
1049
|
+
const area = this.renderRoot.querySelector("textarea");
|
|
1050
|
+
const picker = this.picker;
|
|
1051
|
+
if (!area || !picker) return;
|
|
1052
|
+
const next = insertMention(this.value, picker, area.selectionStart, target);
|
|
1053
|
+
this.value = next.text;
|
|
1054
|
+
this.inserted = [...this.inserted, target];
|
|
1055
|
+
this.picker = null;
|
|
1056
|
+
this.saveDraft();
|
|
1057
|
+
void this.updateComplete.then(() => {
|
|
1058
|
+
area.focus({ preventScroll: true });
|
|
1059
|
+
area.setSelectionRange(next.caret, next.caret);
|
|
1060
|
+
});
|
|
1061
|
+
}
|
|
1062
|
+
/** Picker keys; true when the key was used. */
|
|
1063
|
+
pickerKey(event) {
|
|
1064
|
+
const options = this.pickerOptions();
|
|
1065
|
+
if (!this.picker || options.length === 0) return false;
|
|
1066
|
+
if (event.key === "ArrowDown" || event.key === "ArrowUp") {
|
|
1067
|
+
const step = event.key === "ArrowDown" ? 1 : -1;
|
|
1068
|
+
this.pickerIndex = (this.pickerIndex + step + options.length) % options.length;
|
|
1069
|
+
} else if (event.key === "Enter" && !event.shiftKey && !event.isComposing || event.key === "Tab") {
|
|
1070
|
+
this.chooseMention(options[Math.min(this.pickerIndex, options.length - 1)]);
|
|
1071
|
+
} else if (event.key === "Escape") this.picker = null;
|
|
1072
|
+
else return false;
|
|
1073
|
+
event.preventDefault();
|
|
1074
|
+
return true;
|
|
1075
|
+
}
|
|
487
1076
|
onKeydown(event) {
|
|
1077
|
+
if (this.pickerKey(event)) return;
|
|
488
1078
|
if (event.key === "Escape" && this.emojiOpen) {
|
|
489
1079
|
this.emojiOpen = false;
|
|
490
1080
|
this.focusMessage();
|
|
@@ -523,6 +1113,34 @@ var OfficeUiChatComposer = class extends TeamsElement {
|
|
|
523
1113
|
if (n.length === 0) return "";
|
|
524
1114
|
return n.length === 1 ? `${n[0]} is typing\u2026` : `${n.join(", ")} are typing\u2026`;
|
|
525
1115
|
}
|
|
1116
|
+
mentionList() {
|
|
1117
|
+
const options = this.pickerOptions();
|
|
1118
|
+
if (options.length === 0) return nothing;
|
|
1119
|
+
return html`<ul
|
|
1120
|
+
id="mention-list"
|
|
1121
|
+
class="mentions"
|
|
1122
|
+
role="listbox"
|
|
1123
|
+
aria-label="People to mention"
|
|
1124
|
+
@mousedown=${(event) => event.preventDefault()}
|
|
1125
|
+
>
|
|
1126
|
+
${options.map(
|
|
1127
|
+
(target, index) => html`<li
|
|
1128
|
+
id=${`mention-option-${index}`}
|
|
1129
|
+
role="option"
|
|
1130
|
+
aria-selected=${String(index === this.pickerIndex)}
|
|
1131
|
+
@click=${() => this.chooseMention(target)}
|
|
1132
|
+
>
|
|
1133
|
+
${target.kind === "user" ? html`<office-ui-avatar
|
|
1134
|
+
size="sm"
|
|
1135
|
+
name=${target.name}
|
|
1136
|
+
seed=${target.id}
|
|
1137
|
+
></office-ui-avatar>` : html`<span class="everyone" aria-hidden="true">@</span>`}
|
|
1138
|
+
<span class="name">${target.name}</span>
|
|
1139
|
+
${target.kind === "user" ? nothing : html`<span class="hint">${target.kind === "channel" ? "Notify everyone in this channel" : "Notify the whole team"}</span>`}
|
|
1140
|
+
</li>`
|
|
1141
|
+
)}
|
|
1142
|
+
</ul>`;
|
|
1143
|
+
}
|
|
526
1144
|
render() {
|
|
527
1145
|
const banner = this.editing ? "Editing message" : this.replyingTo !== null ? `Replying to ${this.replyingTo}` : "";
|
|
528
1146
|
return html`
|
|
@@ -572,9 +1190,13 @@ var OfficeUiChatComposer = class extends TeamsElement {
|
|
|
572
1190
|
${icon("close")}
|
|
573
1191
|
</button>
|
|
574
1192
|
</div>` : nothing}
|
|
1193
|
+
${this.mentionList()}
|
|
575
1194
|
<textarea
|
|
576
1195
|
rows="1"
|
|
577
1196
|
aria-label="Message"
|
|
1197
|
+
aria-haspopup="listbox"
|
|
1198
|
+
aria-controls=${this.pickerOptions().length ? "mention-list" : nothing}
|
|
1199
|
+
aria-activedescendant=${this.pickerOptions().length ? `mention-option-${this.pickerIndex}` : nothing}
|
|
578
1200
|
.value=${live(this.value)}
|
|
579
1201
|
placeholder=${this.placeholder}
|
|
580
1202
|
?disabled=${this.disabled}
|
|
@@ -586,6 +1208,11 @@ var OfficeUiChatComposer = class extends TeamsElement {
|
|
|
586
1208
|
}
|
|
587
1209
|
}}
|
|
588
1210
|
@keydown=${this.onKeydown}
|
|
1211
|
+
@keyup=${(event) => {
|
|
1212
|
+
if (["ArrowLeft", "ArrowRight", "Home", "End"].includes(event.key)) this.syncPicker();
|
|
1213
|
+
}}
|
|
1214
|
+
@click=${this.syncPicker}
|
|
1215
|
+
@blur=${() => this.picker = null}
|
|
589
1216
|
></textarea>
|
|
590
1217
|
${this.files.length ? html`<ul class="pending">
|
|
591
1218
|
${this.files.map(
|
|
@@ -668,7 +1295,7 @@ var OfficeUiChatComposer = class extends TeamsElement {
|
|
|
668
1295
|
var defineChatComposer = definer("office-ui-chat-composer", () => OfficeUiChatComposer);
|
|
669
1296
|
|
|
670
1297
|
// raw-css:/home/runner/work/ooxml/ooxml/src/ui/src/teams/chat-list.css?raw
|
|
671
|
-
var chat_list_default = ":host {\n display: block;\n min-height: 0;\n overflow: auto;\n padding: var(--office-space-2) var(--office-space-5);\n}\n.thread-link {\n align-self: flex-start;\n font: inherit;\n color: var(--office-foreground);\n background: var(--office-background);\n border: var(--office-border-width) solid var(--office-teams-divider);\n border-radius: var(--office-radius-md);\n padding: var(--office-space-2);\n cursor: pointer;\n}\n.empty {\n margin: var(--office-space-6) 0;\n color: var(--office-teams-text-subtle);\n text-align: center;\n}\n\n.day {\n display: flex;\n align-items: center;\n gap: var(--office-space-3);\n margin: var(--office-space-4) 0 var(--office-space-2);\n color: var(--office-teams-text-subtle);\n font-size: var(--office-font-size-xs);\n}\n.day::before,\n.day::after {\n content: '';\n flex: 1;\n height: var(--office-border-width);\n background: var(--office-teams-divider);\n}\n\n.msg {\n position: relative;\n display: grid;\n grid-template-columns: 2.3em minmax(0, 1fr);\n column-gap: var(--office-space-3);\n padding: var(--office-space-0) 0;\n}\n.msg[data-grouped='false'] {\n margin-top: var(--office-teams-message-gap, var(--office-space-3));\n}\n.gutter {\n padding-top: var(--office-space-1);\n}\nheader {\n display: flex;\n align-items: baseline;\n gap: var(--office-space-2);\n margin-bottom: var(--office-space-0);\n}\n.author {\n font-weight: var(--office-font-weight-bold);\n}\ntime,\n.edited,\n.file-size {\n color: var(--office-teams-text-subtle);\n font-size: var(--office-font-size-xs);\n}\n\n.bubble {\n display: inline-block;\n max-width: min(100%, 44em);\n padding: var(--office-teams-message-padding, var(--office-space-2) var(--office-space-3));\n border-radius: var(--office-radius-md);\n background: var(--office-teams-bubble);\n line-height: var(--office-line-height);\n overflow-wrap: anywhere;\n}\n.text {\n white-space: pre-wrap;\n}\n.msg[data-own='true'] .bubble {\n background: var(--office-teams-bubble-own);\n}\n.deleted {\n color: var(--office-teams-text-subtle);\n font-style: italic;\n}\nblockquote {\n margin: 0 0 var(--office-space-1);\n padding-inline-start: var(--office-space-2);\n border-inline-start: var(--office-border-width-thick) solid var(--office-teams-brand);\n color: var(--office-teams-text-subtle);\n font-size: var(--office-font-size-sm);\n white-space: normal;\n}\nblockquote strong {\n display: block;\n color: var(--office-foreground);\n}\n\n.files {\n display: flex;\n flex-wrap: wrap;\n gap: var(--office-space-2);\n margin-top: var(--office-space-2);\n white-space: normal;\n}\n.file {\n display: flex;\n align-items: center;\n gap: var(--office-space-3);\n min-width: 14em;\n padding: var(--office-space-2) var(--office-space-3);\n border: var(--office-border-width) solid var(--office-teams-divider);\n border-radius: var(--office-radius-md);\n background: var(--office-background);\n text-align: start;\n}\n.file:hover {\n border-color: var(--office-teams-brand);\n}\n.badge {\n display: grid;\n place-items: center;\n width: 2.2em;\n height: 2.2em;\n border-radius: var(--office-radius);\n background: var(--office-file-other);\n color: var(--office-call-foreground);\n font-weight: var(--office-font-weight-bold);\n}\n.badge[data-kind='docx'] {\n background: var(--office-file-docx);\n}\n.badge[data-kind='xlsx'] {\n background: var(--office-file-xlsx);\n}\n.badge[data-kind='pptx'] {\n background: var(--office-file-pptx);\n}\n.badge[data-kind='vsdx'] {\n background: var(--office-file-vsdx);\n}\n.meta {\n display: grid;\n}\n\n.reactions {\n display: flex;\n flex-wrap: wrap;\n gap: var(--office-space-1);\n margin-top: var(--office-space-1);\n}\n.pill {\n display: inline-flex;\n gap: var(--office-space-1);\n padding: 0 var(--office-space-2);\n border: var(--office-border-width) solid var(--office-teams-divider);\n border-radius: var(--office-radius-full);\n background: var(--office-background);\n font-size: var(--office-font-size-sm);\n}\n.pill[aria-pressed='true'] {\n border-color: var(--office-teams-brand);\n background: var(--office-teams-brand-subtle);\n}\n\n.toolbar {\n position: absolute;\n inset-block-start: calc(-1 * var(--office-space-3));\n inset-inline-end: 0;\n display: none;\n gap: var(--office-space-0);\n padding: var(--office-space-0);\n border: var(--office-border-width) solid var(--office-teams-divider);\n border-radius: var(--office-radius-md);\n background: var(--office-popover);\n box-shadow: var(--office-shadow-teams);\n}\n.msg:hover .toolbar,\n.msg:focus-within .toolbar {\n display: flex;\n}\n.toolbar button {\n display: grid;\n place-items: center;\n min-width: 2em;\n height: 2em;\n border: 0;\n border-radius: var(--office-radius-sm);\n background: transparent;\n}\n.toolbar button:hover {\n background: var(--office-selected);\n}\n";
|
|
1298
|
+
var chat_list_default = ":host {\n display: block;\n min-height: 0;\n overflow: auto;\n padding: var(--office-space-2) var(--office-space-5);\n}\n.thread-link {\n align-self: flex-start;\n font: inherit;\n color: var(--office-foreground);\n background: var(--office-background);\n border: var(--office-border-width) solid var(--office-teams-divider);\n border-radius: var(--office-radius-md);\n padding: var(--office-space-2);\n cursor: pointer;\n}\n.empty {\n margin: var(--office-space-6) 0;\n color: var(--office-teams-text-subtle);\n text-align: center;\n}\n\n.day {\n display: flex;\n align-items: center;\n gap: var(--office-space-3);\n margin: var(--office-space-4) 0 var(--office-space-2);\n color: var(--office-teams-text-subtle);\n font-size: var(--office-font-size-xs);\n}\n.day::before,\n.day::after {\n content: '';\n flex: 1;\n height: var(--office-border-width);\n background: var(--office-teams-divider);\n}\n\n.msg {\n position: relative;\n display: grid;\n grid-template-columns: 2.3em minmax(0, 1fr);\n column-gap: var(--office-space-3);\n padding: var(--office-space-0) 0;\n}\n.msg[data-grouped='false'] {\n margin-top: var(--office-teams-message-gap, var(--office-space-3));\n}\n.gutter {\n padding-top: var(--office-space-1);\n}\nheader {\n display: flex;\n align-items: baseline;\n gap: var(--office-space-2);\n margin-bottom: var(--office-space-0);\n}\n.author {\n font-weight: var(--office-font-weight-bold);\n}\ntime,\n.edited,\n.file-size {\n color: var(--office-teams-text-subtle);\n font-size: var(--office-font-size-xs);\n}\n\n.bubble {\n display: inline-block;\n max-width: min(100%, 44em);\n padding: var(--office-teams-message-padding, var(--office-space-2) var(--office-space-3));\n border-radius: var(--office-radius-md);\n background: var(--office-teams-bubble);\n line-height: var(--office-line-height);\n overflow-wrap: anywhere;\n}\n.text {\n white-space: pre-wrap;\n}\n.msg[data-own='true'] .bubble {\n background: var(--office-teams-bubble-own);\n}\n.deleted {\n color: var(--office-teams-text-subtle);\n font-style: italic;\n}\nblockquote {\n margin: 0 0 var(--office-space-1);\n padding-inline-start: var(--office-space-2);\n border-inline-start: var(--office-border-width-thick) solid var(--office-teams-brand);\n color: var(--office-teams-text-subtle);\n font-size: var(--office-font-size-sm);\n white-space: normal;\n}\nblockquote strong {\n display: block;\n color: var(--office-foreground);\n}\n\n.files {\n display: flex;\n flex-wrap: wrap;\n gap: var(--office-space-2);\n margin-top: var(--office-space-2);\n white-space: normal;\n}\n.file {\n display: flex;\n align-items: center;\n gap: var(--office-space-3);\n min-width: 14em;\n padding: var(--office-space-2) var(--office-space-3);\n border: var(--office-border-width) solid var(--office-teams-divider);\n border-radius: var(--office-radius-md);\n background: var(--office-background);\n text-align: start;\n}\n.file:hover {\n border-color: var(--office-teams-brand);\n}\n.badge {\n display: grid;\n place-items: center;\n width: 2.2em;\n height: 2.2em;\n border-radius: var(--office-radius);\n background: var(--office-file-other);\n color: var(--office-call-foreground);\n font-weight: var(--office-font-weight-bold);\n}\n.badge[data-kind='docx'] {\n background: var(--office-file-docx);\n}\n.badge[data-kind='xlsx'] {\n background: var(--office-file-xlsx);\n}\n.badge[data-kind='pptx'] {\n background: var(--office-file-pptx);\n}\n.badge[data-kind='vsdx'] {\n background: var(--office-file-vsdx);\n}\n.meta {\n display: grid;\n}\n\n.reactions {\n display: flex;\n flex-wrap: wrap;\n gap: var(--office-space-1);\n margin-top: var(--office-space-1);\n}\n.pill {\n display: inline-flex;\n gap: var(--office-space-1);\n padding: 0 var(--office-space-2);\n border: var(--office-border-width) solid var(--office-teams-divider);\n border-radius: var(--office-radius-full);\n background: var(--office-background);\n font-size: var(--office-font-size-sm);\n}\n.pill[aria-pressed='true'] {\n border-color: var(--office-teams-brand);\n background: var(--office-teams-brand-subtle);\n}\n\n.toolbar {\n position: absolute;\n inset-block-start: calc(-1 * var(--office-space-3));\n inset-inline-end: 0;\n display: none;\n gap: var(--office-space-0);\n padding: var(--office-space-0);\n border: var(--office-border-width) solid var(--office-teams-divider);\n border-radius: var(--office-radius-md);\n background: var(--office-popover);\n box-shadow: var(--office-shadow-teams);\n}\n.msg:hover .toolbar,\n.msg:focus-within .toolbar {\n display: flex;\n}\n.toolbar button {\n display: grid;\n place-items: center;\n min-width: 2em;\n height: 2em;\n border: 0;\n border-radius: var(--office-radius-sm);\n background: transparent;\n}\n.toolbar button:hover {\n background: var(--office-selected);\n}\n\n.msg:focus {\n outline: none;\n}\n.pin-mark {\n display: inline-flex;\n align-items: center;\n gap: var(--office-space-1);\n color: var(--office-teams-brand);\n font-size: var(--office-font-size-xs);\n}\n.pin-mark svg {\n width: 1em;\n height: 1em;\n}\n@media (pointer: coarse) {\n .toolbar button {\n min-width: var(--office-touch-target, 44px);\n height: var(--office-touch-target, 44px);\n }\n}\n\n/* @mentions: the name in the brand colour; a mention of you (or of everyone) gets a chip. */\n.mention {\n color: var(--office-teams-brand);\n font-weight: 600;\n}\n.mention[data-self='true'] {\n padding: 0 var(--office-space-1);\n border-radius: var(--office-radius);\n background: var(--office-teams-brand-subtle);\n}\n.msg[data-mentions-you='true'] .bubble {\n box-shadow: inset var(--office-border-width-thick) 0 0 var(--office-teams-brand);\n}\n\n/* A message opened from Activity or the pinned bar flashes once. */\n.msg[data-highlight='true'] .bubble {\n animation: flash 2.4s ease-out;\n}\n@keyframes flash {\n from {\n background: var(--office-teams-brand-subtle);\n outline: var(--office-border-width-thick) solid var(--office-teams-brand);\n }\n to {\n outline: var(--office-border-width-thick) solid transparent;\n }\n}\n\n.system {\n margin: var(--office-space-3) 0;\n color: var(--office-teams-text-subtle);\n font-size: var(--office-font-size-sm);\n text-align: center;\n}\n.system:focus {\n outline: none;\n}\n\n.meeting-card {\n display: grid;\n grid-template-columns: auto minmax(0, 1fr) auto auto;\n align-items: center;\n gap: var(--office-space-2) var(--office-space-3);\n min-width: min(22em, 100%);\n margin-top: var(--office-space-2);\n padding: var(--office-space-3);\n border: var(--office-border-width) solid var(--office-teams-divider);\n border-inline-start: var(--office-border-width-thick) solid var(--office-teams-brand);\n border-radius: var(--office-radius-md);\n background: var(--office-background);\n white-space: normal;\n}\n.meeting-card[data-gone='true'] {\n grid-template-columns: auto minmax(0, 1fr);\n color: var(--office-teams-text-subtle);\n}\n.meeting-icon {\n display: grid;\n place-items: center;\n width: 2.2em;\n height: 2.2em;\n border-radius: var(--office-radius);\n background: var(--office-teams-brand-subtle);\n color: var(--office-teams-brand);\n}\n.meeting-meta {\n display: grid;\n min-width: 0;\n}\n.meeting-title {\n font-weight: var(--office-font-weight-bold);\n}\n.meeting-time {\n color: var(--office-teams-text-subtle);\n font-size: var(--office-font-size-sm);\n}\n.meeting-open,\n.meeting-join {\n padding: var(--office-space-1) var(--office-space-3);\n border: var(--office-border-width) solid var(--office-teams-divider);\n border-radius: var(--office-radius-md);\n background: var(--office-background);\n color: inherit;\n font: inherit;\n cursor: pointer;\n}\n.meeting-join {\n border-color: transparent;\n background: var(--office-teams-brand);\n color: var(--office-teams-brand-foreground);\n}\n.meeting-join:hover {\n background: var(--office-teams-brand-hover);\n}\n@media (max-width: 40em) {\n .meeting-card {\n grid-template-columns: auto minmax(0, 1fr);\n }\n .meeting-open,\n .meeting-join {\n grid-column: 1 / -1;\n min-height: 2.75em;\n }\n}\n";
|
|
672
1299
|
|
|
673
1300
|
// src/teams/chat-list.ts
|
|
674
1301
|
var QUICK_REACTIONS = ["\u{1F44D}", "\u2764\uFE0F", "\u{1F602}", "\u{1F62E}", "\u{1F622}", "\u{1F389}"];
|
|
@@ -685,7 +1312,10 @@ var OfficeUiChatList = class extends TeamsElement {
|
|
|
685
1312
|
static properties = {
|
|
686
1313
|
messages: { attribute: false },
|
|
687
1314
|
selfId: { type: String, attribute: "self-id" },
|
|
688
|
-
replyCounts: { attribute: false }
|
|
1315
|
+
replyCounts: { attribute: false },
|
|
1316
|
+
pinnedIds: { attribute: false },
|
|
1317
|
+
highlightId: { type: String, attribute: "highlight-id" },
|
|
1318
|
+
meetings: { attribute: false }
|
|
689
1319
|
};
|
|
690
1320
|
stickToBottom = true;
|
|
691
1321
|
constructor() {
|
|
@@ -693,6 +1323,9 @@ var OfficeUiChatList = class extends TeamsElement {
|
|
|
693
1323
|
this.messages = [];
|
|
694
1324
|
this.selfId = "";
|
|
695
1325
|
this.replyCounts = {};
|
|
1326
|
+
this.pinnedIds = [];
|
|
1327
|
+
this.highlightId = "";
|
|
1328
|
+
this.meetings = {};
|
|
696
1329
|
}
|
|
697
1330
|
connectedCallback() {
|
|
698
1331
|
super.connectedCallback();
|
|
@@ -712,6 +1345,11 @@ var OfficeUiChatList = class extends TeamsElement {
|
|
|
712
1345
|
const rows = [];
|
|
713
1346
|
let previous;
|
|
714
1347
|
for (const m of this.messages) {
|
|
1348
|
+
if (m.system && !m.deleted) {
|
|
1349
|
+
rows.push(html`<div class="system" data-message-id=${m.id} tabindex="-1">${m.text}</div>`);
|
|
1350
|
+
previous = void 0;
|
|
1351
|
+
continue;
|
|
1352
|
+
}
|
|
715
1353
|
if (!previous || dayLabel(previous.ts) !== dayLabel(m.ts))
|
|
716
1354
|
rows.push(html`<div class="day"><span>${dayLabel(m.ts)}</span></div>`);
|
|
717
1355
|
const grouped = previous !== void 0 && previous.authorId === m.authorId && m.ts - previous.ts < GROUP_MS && !m.replyTo && dayLabel(previous.ts) === dayLabel(m.ts);
|
|
@@ -726,9 +1364,12 @@ var OfficeUiChatList = class extends TeamsElement {
|
|
|
726
1364
|
return html`
|
|
727
1365
|
<article
|
|
728
1366
|
class="msg"
|
|
1367
|
+
tabindex="-1"
|
|
729
1368
|
data-message-id=${m.id}
|
|
730
1369
|
data-own=${String(own)}
|
|
1370
|
+
data-highlight=${String(m.id === this.highlightId)}
|
|
731
1371
|
data-grouped=${String(grouped)}
|
|
1372
|
+
data-mentions-you=${String(!m.deleted && mentionsUser(m, this.selfId) && !own)}
|
|
732
1373
|
>
|
|
733
1374
|
<div class="gutter">
|
|
734
1375
|
${grouped ? nothing : html`<office-ui-avatar name=${m.authorName} seed=${m.authorId}></office-ui-avatar>`}
|
|
@@ -738,12 +1379,14 @@ var OfficeUiChatList = class extends TeamsElement {
|
|
|
738
1379
|
<span class="author">${m.authorName}</span>
|
|
739
1380
|
<time>${formatTime(m.ts)}</time>
|
|
740
1381
|
</header>`}
|
|
1382
|
+
${this.pinMark(m)}
|
|
741
1383
|
<div class="bubble">
|
|
742
1384
|
${parent ? html`<blockquote>
|
|
743
1385
|
<strong>${parent.authorName}</strong
|
|
744
1386
|
>${parent.deleted ? "This message was deleted" : parent.text.slice(0, 120)}
|
|
745
1387
|
</blockquote>` : nothing}
|
|
746
|
-
${m.deleted ? html`<span class="deleted">This message was deleted</span>` : html`<span class="text">${m
|
|
1388
|
+
${m.deleted ? html`<span class="deleted">This message was deleted</span>` : html`<span class="text">${this.body(m)}</span>${m.editedAt ? html` <span class="edited">(edited)</span>` : nothing}`}
|
|
1389
|
+
${!m.deleted && m.meetingId ? this.meetingCard(m.meetingId) : nothing}
|
|
747
1390
|
${!m.deleted && m.attachments?.length ? this.files(m.attachments) : nothing}
|
|
748
1391
|
${!m.deleted && m.tabId ? html`<button class="thread-link" type="button" @click=${() => this.fire("office-chat-open-tab", { tabId: m.tabId })}>Open tab</button>` : nothing}
|
|
749
1392
|
</div>
|
|
@@ -768,6 +1411,47 @@ var OfficeUiChatList = class extends TeamsElement {
|
|
|
768
1411
|
</article>
|
|
769
1412
|
`;
|
|
770
1413
|
}
|
|
1414
|
+
/** Plain runs and highlighted mentions (the name without its `@`, as in Teams), with no whitespace between them. */
|
|
1415
|
+
body(m) {
|
|
1416
|
+
return mentionSegments(m.text, m.mentions).map(
|
|
1417
|
+
(segment) => segment.mention ? html`<span
|
|
1418
|
+
class="mention"
|
|
1419
|
+
data-self=${String(segment.mention.kind !== "user" || segment.mention.id === this.selfId)}
|
|
1420
|
+
>${segment.text.slice(1)}</span
|
|
1421
|
+
>` : segment.text
|
|
1422
|
+
);
|
|
1423
|
+
}
|
|
1424
|
+
meetingCard(meetingId) {
|
|
1425
|
+
const card = this.meetings[meetingId];
|
|
1426
|
+
if (!card)
|
|
1427
|
+
return html`<div class="meeting-card" data-gone="true">
|
|
1428
|
+
<span class="meeting-icon">${icon("calendar")}</span>
|
|
1429
|
+
<span class="meeting-meta">
|
|
1430
|
+
<span class="meeting-title">This meeting was canceled or is not in your calendar</span>
|
|
1431
|
+
</span>
|
|
1432
|
+
</div>`;
|
|
1433
|
+
return html`<div class="meeting-card">
|
|
1434
|
+
<span class="meeting-icon">${icon("calendar")}</span>
|
|
1435
|
+
<span class="meeting-meta">
|
|
1436
|
+
<span class="meeting-title">${card.title}</span>
|
|
1437
|
+
<span class="meeting-time">${formatWhen(card.start, card.end)}</span>
|
|
1438
|
+
</span>
|
|
1439
|
+
<button
|
|
1440
|
+
type="button"
|
|
1441
|
+
class="meeting-open"
|
|
1442
|
+
@click=${() => this.fire("office-chat-meeting", { meetingId, action: "open" })}
|
|
1443
|
+
>
|
|
1444
|
+
Details
|
|
1445
|
+
</button>
|
|
1446
|
+
<button
|
|
1447
|
+
type="button"
|
|
1448
|
+
class="meeting-join"
|
|
1449
|
+
@click=${() => this.fire("office-chat-meeting", { meetingId, action: "join" })}
|
|
1450
|
+
>
|
|
1451
|
+
${card.live ? "Join now" : "Join"}
|
|
1452
|
+
</button>
|
|
1453
|
+
</div>`;
|
|
1454
|
+
}
|
|
771
1455
|
toolbar(m, own) {
|
|
772
1456
|
return html`
|
|
773
1457
|
<div class="toolbar" role="toolbar" aria-label="Message actions">
|
|
@@ -788,6 +1472,7 @@ var OfficeUiChatList = class extends TeamsElement {
|
|
|
788
1472
|
>
|
|
789
1473
|
${icon("reply")}
|
|
790
1474
|
</button>
|
|
1475
|
+
${this.pinButton(m)}
|
|
791
1476
|
${own ? html`<button
|
|
792
1477
|
type="button"
|
|
793
1478
|
title="Edit"
|
|
@@ -807,6 +1492,22 @@ var OfficeUiChatList = class extends TeamsElement {
|
|
|
807
1492
|
</div>
|
|
808
1493
|
`;
|
|
809
1494
|
}
|
|
1495
|
+
pinMark(m) {
|
|
1496
|
+
return !m.deleted && this.pinnedIds.includes(m.id) ? html`<span class="pin-mark">${icon("pin")} Pinned</span>` : nothing;
|
|
1497
|
+
}
|
|
1498
|
+
pinButton(m) {
|
|
1499
|
+
const pinned = this.pinnedIds.includes(m.id);
|
|
1500
|
+
const label = pinned ? "Unpin" : "Pin";
|
|
1501
|
+
return html`<button
|
|
1502
|
+
type="button"
|
|
1503
|
+
title=${label}
|
|
1504
|
+
aria-label=${label}
|
|
1505
|
+
aria-pressed=${String(pinned)}
|
|
1506
|
+
@click=${() => this.fire(pinned ? "office-chat-unpin" : "office-chat-pin", { messageId: m.id })}
|
|
1507
|
+
>
|
|
1508
|
+
${icon("pin")}
|
|
1509
|
+
</button>`;
|
|
1510
|
+
}
|
|
810
1511
|
files(files) {
|
|
811
1512
|
return html`<div class="files">
|
|
812
1513
|
${files.map(
|
|
@@ -830,6 +1531,161 @@ var OfficeUiChatList = class extends TeamsElement {
|
|
|
830
1531
|
};
|
|
831
1532
|
var defineChatList = definer("office-ui-chat-list", () => OfficeUiChatList);
|
|
832
1533
|
|
|
1534
|
+
// raw-css:/home/runner/work/ooxml/ooxml/src/ui/src/teams/chat-sidebar.css?raw
|
|
1535
|
+
var chat_sidebar_default = ":host {\n display: block;\n overflow: auto;\n}\nheader {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: var(--office-space-3) var(--office-space-3) var(--office-space-2) var(--office-space-4);\n}\nh2 {\n margin: 0;\n font-size: var(--office-font-size-lg);\n}\n.new {\n display: grid;\n place-items: center;\n width: 2.2em;\n height: 2.2em;\n border: 0;\n border-radius: var(--office-radius-md);\n background: transparent;\n color: var(--office-teams-brand);\n}\n.new:hover {\n background: var(--office-selected);\n}\nul {\n margin: 0;\n padding: 0 var(--office-space-2);\n list-style: none;\n}\n.empty {\n margin: var(--office-space-4);\n color: var(--office-teams-text-subtle);\n}\n.row {\n position: relative;\n display: flex;\n align-items: center;\n gap: var(--office-space-3);\n width: 100%;\n padding: var(--office-space-2) var(--office-space-3);\n border: 0;\n border-radius: var(--office-radius);\n background: transparent;\n color: var(--office-teams-text-subtle);\n text-align: start;\n}\n.row:hover {\n background: var(--office-selected);\n}\n.row[aria-current='true'] {\n background: var(--office-teams-brand-subtle);\n color: var(--office-foreground);\n}\n.row[aria-current='true']::before {\n content: '';\n position: absolute;\n inset-inline-start: 0;\n inset-block: 20%;\n width: var(--office-space-1);\n border-radius: var(--office-radius-full);\n background: var(--office-teams-brand);\n}\n.group {\n display: grid;\n place-items: center;\n flex: none;\n width: 2.3em;\n height: 2.3em;\n border-radius: var(--office-radius-full);\n background: var(--office-teams-bubble);\n color: var(--office-teams-brand);\n}\n.text {\n display: grid;\n flex: 1;\n min-width: 0;\n}\n.line {\n display: flex;\n align-items: baseline;\n gap: var(--office-space-2);\n}\n.title {\n flex: 1;\n min-width: 0;\n overflow: hidden;\n color: var(--office-foreground);\n text-overflow: ellipsis;\n white-space: nowrap;\n}\ntime {\n font-size: var(--office-font-size-xs);\n}\n.preview {\n overflow: hidden;\n font-size: var(--office-font-size-sm);\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.row[data-unread='true'] .title,\n.row[data-unread='true'] .preview {\n color: var(--office-foreground);\n font-weight: var(--office-font-weight-bold);\n}\n.live {\n display: grid;\n color: var(--office-call-live);\n}\n.count {\n min-width: 1.6em;\n padding: 0 var(--office-space-1);\n border-radius: var(--office-radius-full);\n background: var(--office-teams-brand);\n color: var(--office-teams-brand-foreground);\n font-size: var(--office-font-size-xs);\n line-height: 1.6;\n text-align: center;\n}\n@media (pointer: coarse) {\n .new,\n .row {\n min-width: var(--office-touch-target, 44px);\n min-height: var(--office-touch-target, 44px);\n }\n}\n";
|
|
1536
|
+
|
|
1537
|
+
// src/teams/chat-sidebar.ts
|
|
1538
|
+
function stamp(ts) {
|
|
1539
|
+
if (!ts) return "";
|
|
1540
|
+
return dayLabel(ts) === "Today" ? formatTime(ts) : new Date(ts).toLocaleDateString([], { month: "short", day: "numeric" });
|
|
1541
|
+
}
|
|
1542
|
+
var OfficeUiChatSidebar = class extends TeamsElement {
|
|
1543
|
+
static styles = withStyles(chat_sidebar_default);
|
|
1544
|
+
static properties = {
|
|
1545
|
+
chats: { attribute: false },
|
|
1546
|
+
selectedId: { type: String, attribute: "selected-id" }
|
|
1547
|
+
};
|
|
1548
|
+
constructor() {
|
|
1549
|
+
super();
|
|
1550
|
+
this.chats = [];
|
|
1551
|
+
this.selectedId = "";
|
|
1552
|
+
}
|
|
1553
|
+
render() {
|
|
1554
|
+
return html`
|
|
1555
|
+
<header>
|
|
1556
|
+
<h2>Chat</h2>
|
|
1557
|
+
<button
|
|
1558
|
+
class="new"
|
|
1559
|
+
type="button"
|
|
1560
|
+
title="New chat"
|
|
1561
|
+
aria-label="New chat"
|
|
1562
|
+
@click=${() => this.fire("office-chat-new", {})}
|
|
1563
|
+
>
|
|
1564
|
+
${icon("plus")}
|
|
1565
|
+
</button>
|
|
1566
|
+
</header>
|
|
1567
|
+
${this.chats.length === 0 ? html`<p class="empty">No chats yet. Start one with the plus button.</p>` : html`<ul>
|
|
1568
|
+
${this.chats.map((c) => this.row(c))}
|
|
1569
|
+
</ul>`}
|
|
1570
|
+
`;
|
|
1571
|
+
}
|
|
1572
|
+
row(c) {
|
|
1573
|
+
const other = c.kind === "direct" ? c.members.find((m) => !m.self) : void 0;
|
|
1574
|
+
const preview = c.lastMessage ? c.lastMessage.system ? c.lastMessage.text : c.lastMessage.mine ? `You: ${c.lastMessage.text}` : c.kind === "direct" ? c.lastMessage.text : `${c.lastMessage.authorName}: ${c.lastMessage.text}` : "No messages yet";
|
|
1575
|
+
return html`
|
|
1576
|
+
<li>
|
|
1577
|
+
<button
|
|
1578
|
+
class="row"
|
|
1579
|
+
type="button"
|
|
1580
|
+
aria-current=${c.id === this.selectedId ? "true" : "false"}
|
|
1581
|
+
data-unread=${c.unread ? "true" : "false"}
|
|
1582
|
+
@click=${() => this.fire("office-chat-select", { id: c.id })}
|
|
1583
|
+
>
|
|
1584
|
+
${other ? html`<office-ui-avatar
|
|
1585
|
+
name=${other.name}
|
|
1586
|
+
seed=${other.id}
|
|
1587
|
+
presence=${other.availability}
|
|
1588
|
+
></office-ui-avatar>` : html`<span class="group" aria-hidden="true"
|
|
1589
|
+
>${icon(c.meetingId ? "calendar" : "users")}</span
|
|
1590
|
+
>`}
|
|
1591
|
+
<span class="text">
|
|
1592
|
+
<span class="line">
|
|
1593
|
+
<span class="title">${c.title}</span>
|
|
1594
|
+
<time>${stamp(c.ts)}</time>
|
|
1595
|
+
</span>
|
|
1596
|
+
<span class="preview">${preview}</span>
|
|
1597
|
+
</span>
|
|
1598
|
+
${c.live ? html`<span class="live" title="Call in progress">${icon("video")}</span>` : nothing}
|
|
1599
|
+
${c.unread ? html`<span class="count" aria-label=${`${c.unread} unread`}
|
|
1600
|
+
>${c.unread > 99 ? "99+" : c.unread}</span
|
|
1601
|
+
>` : nothing}
|
|
1602
|
+
</button>
|
|
1603
|
+
</li>
|
|
1604
|
+
`;
|
|
1605
|
+
}
|
|
1606
|
+
};
|
|
1607
|
+
var defineChatSidebar = definer("office-ui-chat-sidebar", () => OfficeUiChatSidebar);
|
|
1608
|
+
|
|
1609
|
+
// raw-css:/home/runner/work/ooxml/ooxml/src/ui/src/teams/people-picker.css?raw
|
|
1610
|
+
var people_picker_default = ":host {\n display: grid;\n gap: var(--office-space-2);\n min-width: 0;\n}\ninput[type='search'] {\n min-width: 0;\n box-sizing: border-box;\n padding: var(--office-space-3);\n font: inherit;\n color: inherit;\n background: var(--office-field-background);\n border: var(--office-border-width) solid var(--office-field-border);\n border-radius: var(--office-radius-md);\n}\n.chips,\n.list {\n margin: 0;\n padding: 0;\n list-style: none;\n}\n.chips {\n display: flex;\n flex-wrap: wrap;\n gap: var(--office-space-1);\n}\n.chip {\n padding: var(--office-space-1) var(--office-space-3);\n border: var(--office-border-width) solid var(--office-teams-divider);\n border-radius: var(--office-radius-full);\n background: var(--office-teams-brand-subtle);\n color: inherit;\n font: inherit;\n cursor: pointer;\n}\n.list {\n max-height: 14em;\n overflow: auto;\n border: var(--office-border-width) solid var(--office-teams-divider);\n border-radius: var(--office-radius-md);\n}\n.list label {\n display: flex;\n align-items: center;\n gap: var(--office-space-3);\n padding: var(--office-space-2) var(--office-space-3);\n cursor: pointer;\n}\n.list label:hover {\n background: var(--office-selected);\n}\n.name {\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.none {\n margin: 0;\n color: var(--office-teams-text-subtle);\n}\n@media (pointer: coarse) {\n .list label,\n .chip {\n min-height: var(--office-touch-target, 44px);\n }\n}\n";
|
|
1611
|
+
|
|
1612
|
+
// src/teams/people-picker.ts
|
|
1613
|
+
var OfficeUiPeoplePicker = class extends TeamsElement {
|
|
1614
|
+
static styles = withStyles(people_picker_default);
|
|
1615
|
+
static properties = {
|
|
1616
|
+
contacts: { attribute: false },
|
|
1617
|
+
selected: { attribute: false },
|
|
1618
|
+
exclude: { attribute: false },
|
|
1619
|
+
label: { type: String },
|
|
1620
|
+
query: { state: true }
|
|
1621
|
+
};
|
|
1622
|
+
constructor() {
|
|
1623
|
+
super();
|
|
1624
|
+
this.contacts = [];
|
|
1625
|
+
this.selected = [];
|
|
1626
|
+
this.exclude = [];
|
|
1627
|
+
this.label = "People";
|
|
1628
|
+
this.query = "";
|
|
1629
|
+
}
|
|
1630
|
+
toggle(id) {
|
|
1631
|
+
const next = this.selected.includes(id) ? this.selected.filter((s) => s !== id) : [...this.selected, id];
|
|
1632
|
+
this.fire("office-people-change", { selected: next });
|
|
1633
|
+
}
|
|
1634
|
+
render() {
|
|
1635
|
+
const q = this.query.trim().toLocaleLowerCase();
|
|
1636
|
+
const offered = this.contacts.filter(
|
|
1637
|
+
(c) => !this.exclude.includes(c.id) && (!q || c.name.toLocaleLowerCase().includes(q))
|
|
1638
|
+
);
|
|
1639
|
+
const chosen = this.contacts.filter((c) => this.selected.includes(c.id));
|
|
1640
|
+
return html`
|
|
1641
|
+
${chosen.length ? html`<ul class="chips" aria-label="Selected people">
|
|
1642
|
+
${chosen.map(
|
|
1643
|
+
(c) => html`<li>
|
|
1644
|
+
<button
|
|
1645
|
+
type="button"
|
|
1646
|
+
class="chip"
|
|
1647
|
+
aria-label=${`Remove ${c.name}`}
|
|
1648
|
+
@click=${() => this.toggle(c.id)}
|
|
1649
|
+
>
|
|
1650
|
+
${c.name} <span aria-hidden="true">×</span>
|
|
1651
|
+
</button>
|
|
1652
|
+
</li>`
|
|
1653
|
+
)}
|
|
1654
|
+
</ul>` : nothing}
|
|
1655
|
+
<input
|
|
1656
|
+
type="search"
|
|
1657
|
+
placeholder="Search people"
|
|
1658
|
+
aria-label=${`Search ${this.label.toLocaleLowerCase()}`}
|
|
1659
|
+
.value=${this.query}
|
|
1660
|
+
@input=${(e) => this.query = e.target.value}
|
|
1661
|
+
/>
|
|
1662
|
+
${offered.length === 0 ? html`<p class="none">
|
|
1663
|
+
${this.contacts.length === 0 ? "Nobody else has joined this workspace yet." : "No one matches that search."}
|
|
1664
|
+
</p>` : html`<ul class="list" role="group" aria-label=${this.label}>
|
|
1665
|
+
${offered.map(
|
|
1666
|
+
(c) => html`<li>
|
|
1667
|
+
<label>
|
|
1668
|
+
<input
|
|
1669
|
+
type="checkbox"
|
|
1670
|
+
.checked=${this.selected.includes(c.id)}
|
|
1671
|
+
@change=${() => this.toggle(c.id)}
|
|
1672
|
+
/>
|
|
1673
|
+
<office-ui-avatar
|
|
1674
|
+
size="sm"
|
|
1675
|
+
name=${c.name}
|
|
1676
|
+
seed=${c.id}
|
|
1677
|
+
presence=${c.availability}
|
|
1678
|
+
></office-ui-avatar>
|
|
1679
|
+
<span class="name">${c.name}</span>
|
|
1680
|
+
</label>
|
|
1681
|
+
</li>`
|
|
1682
|
+
)}
|
|
1683
|
+
</ul>`}
|
|
1684
|
+
`;
|
|
1685
|
+
}
|
|
1686
|
+
};
|
|
1687
|
+
var definePeoplePicker = definer("office-ui-people-picker", () => OfficeUiPeoplePicker);
|
|
1688
|
+
|
|
833
1689
|
// raw-css:/home/runner/work/ooxml/ooxml/src/ui/src/teams/prejoin.css?raw
|
|
834
1690
|
var prejoin_default = ":host {\n display: grid;\n place-items: center;\n padding: var(--office-space-5);\n background: var(--office-teams-panel);\n}\n.card {\n display: grid;\n grid-template-columns: minmax(0, 3fr) minmax(16em, 2fr);\n width: min(60em, 100%);\n overflow: hidden;\n border-radius: var(--office-radius-lg);\n background: var(--office-background);\n box-shadow: var(--office-shadow-teams);\n}\n.stage {\n position: relative;\n display: grid;\n place-content: center;\n justify-items: center;\n gap: var(--office-space-3);\n min-height: 18em;\n background: var(--office-call-background);\n color: var(--office-call-muted-foreground);\n}\n.stage video {\n position: absolute;\n inset: 0;\n width: 100%;\n height: 100%;\n object-fit: cover;\n transform: scaleX(-1);\n}\n.panel {\n display: flex;\n flex-direction: column;\n gap: var(--office-space-3);\n padding: var(--office-space-5);\n}\nh2 {\n margin: 0;\n font-size: var(--office-font-size-lg);\n}\n.for {\n margin: 0;\n color: var(--office-teams-text-subtle);\n}\n.switch {\n position: relative;\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: var(--office-space-3);\n border: var(--office-border-width) solid var(--office-teams-divider);\n border-radius: var(--office-radius-md);\n cursor: pointer;\n}\n.what {\n display: inline-flex;\n align-items: center;\n gap: var(--office-space-2);\n}\n.switch input {\n position: absolute;\n inset: 0;\n margin: 0;\n opacity: 0;\n cursor: pointer;\n}\n.track {\n position: relative;\n width: 2.6em;\n height: 1.4em;\n border-radius: var(--office-radius-full);\n background: var(--office-border);\n transition: background var(--office-duration-fast);\n}\n.track::after {\n content: '';\n position: absolute;\n inset-block-start: 0.2em;\n inset-inline-start: 0.2em;\n width: 1em;\n height: 1em;\n border-radius: 50%;\n background: var(--office-background);\n transition: transform var(--office-duration-fast);\n}\n.switch input:checked ~ .track {\n background: var(--office-teams-brand);\n}\n.switch input:checked ~ .track::after {\n transform: translateX(1.2em);\n}\n.switch:has(input:focus-visible) {\n outline: var(--office-focus-width) solid var(--office-ring);\n}\n.actions {\n display: flex;\n justify-content: flex-end;\n gap: var(--office-space-2);\n margin-top: auto;\n}\n.actions button {\n padding: var(--office-space-2) var(--office-space-5);\n border: var(--office-border-width) solid var(--office-teams-divider);\n border-radius: var(--office-radius-md);\n background: var(--office-background);\n font-weight: var(--office-font-weight-bold);\n}\n.actions .join {\n border-color: transparent;\n background: var(--office-teams-brand);\n color: var(--office-teams-brand-foreground);\n}\n.actions .join:hover:not(:disabled) {\n background: var(--office-teams-brand-hover);\n}\n.actions button:disabled {\n opacity: 0.6;\n cursor: wait;\n}\n@media (max-width: 767px) {\n .card {\n grid-template-columns: 1fr;\n }\n}\n";
|
|
835
1691
|
|
|
@@ -912,13 +1768,15 @@ var OfficeUiPrejoin = class extends TeamsElement {
|
|
|
912
1768
|
};
|
|
913
1769
|
var definePrejoin = definer("office-ui-prejoin", () => OfficeUiPrejoin);
|
|
914
1770
|
var TeamsController = class {
|
|
915
|
-
constructor(host, onNotice) {
|
|
1771
|
+
constructor(host, onNotice, onNotification = () => void 0) {
|
|
916
1772
|
this.host = host;
|
|
917
1773
|
this.onNotice = onNotice;
|
|
1774
|
+
this.onNotification = onNotification;
|
|
918
1775
|
host.addController(this);
|
|
919
1776
|
}
|
|
920
1777
|
host;
|
|
921
1778
|
onNotice;
|
|
1779
|
+
onNotification;
|
|
922
1780
|
client = null;
|
|
923
1781
|
state = null;
|
|
924
1782
|
off = [];
|
|
@@ -933,7 +1791,8 @@ var TeamsController = class {
|
|
|
933
1791
|
this.state = client.getState();
|
|
934
1792
|
this.host.requestUpdate();
|
|
935
1793
|
}),
|
|
936
|
-
client.on("notice", this.onNotice)
|
|
1794
|
+
client.on("notice", this.onNotice),
|
|
1795
|
+
client.on("notification", this.onNotification)
|
|
937
1796
|
];
|
|
938
1797
|
this.host.requestUpdate();
|
|
939
1798
|
}
|
|
@@ -1929,7 +2788,7 @@ function defineTeamsFilesPanel() {
|
|
|
1929
2788
|
}
|
|
1930
2789
|
|
|
1931
2790
|
// raw-css:/home/runner/work/ooxml/ooxml/src/ui/src/teams/app/teams-settings.css?raw
|
|
1932
|
-
var teams_settings_default = ":host {\n font: var(--office-font-size) var(--office-font);\n color: var(--office-foreground);\n}\ndialog {\n box-sizing: border-box;\n width: min(76em, 94vw);\n max-height: 90dvh;\n overflow: hidden;\n padding: 0;\n border: var(--office-border-width) solid var(--office-teams-divider);\n border-radius: var(--office-radius-lg);\n background: var(--office-popover);\n color: inherit;\n box-shadow: var(--office-shadow-teams);\n}\ndialog::backdrop {\n background: var(--office-overlay);\n}\n:host([embedded]) {\n display: block;\n height: 100%;\n min-height: 0;\n}\n:host([embedded]:not([open])) {\n display: none;\n}\n:host([embedded]) dialog {\n position: relative;\n width: 100%;\n height: 100%;\n max-width: none;\n max-height: none;\n margin: 0;\n border: 0;\n border-radius: 0;\n box-shadow: none;\n}\n:host([embedded]) dialog[open] {\n display: flex;\n flex-direction: column;\n}\n:host([embedded]) .settings-layout {\n flex: 1;\n height: auto;\n}\nform {\n display: grid;\n gap: var(--office-space-3);\n padding: var(--office-space-5);\n}\nheader {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: var(--office-space-4) var(--office-space-5);\n border-block-end: var(--office-border-width) solid var(--office-teams-divider);\n gap: var(--office-space-3);\n}\nheader input {\n margin-inline-start: auto;\n width: min(24em, 50%);\n min-width: 0;\n}\n.settings-results ul {\n list-style: none;\n padding: 0;\n display: grid;\n gap: var(--office-space-3);\n}\n.settings-results button {\n display: grid;\n gap: var(--office-space-2);\n width: 100%;\n text-align: start;\n}\n.settings-results button:hover {\n background: var(--office-selected);\n}\nh1 {\n margin: 0;\n font-size: var(--office-font-size-lg);\n}\n.settings-layout {\n display: grid;\n grid-template-columns: 19em minmax(0, 1fr);\n height: min(42em, calc(90dvh - 5em));\n min-height: 0;\n}\nnav {\n min-height: 0;\n overflow-y: auto;\n display: flex;\n flex-direction: column;\n gap: var(--office-space-1);\n padding: var(--office-space-3);\n background: var(--office-teams-panel);\n border-inline-end: var(--office-border-width) solid var(--office-teams-divider);\n}\nnav button {\n display: flex;\n align-items: center;\n gap: var(--office-space-3);\n min-height: 3em;\n text-align: start;\n border: 0;\n background: transparent;\n}\nnav button:hover {\n background: var(--office-selected);\n}\n.icon {\n width: 1.4em;\n height: 1.4em;\n flex-shrink: 0;\n fill: none;\n stroke: currentColor;\n stroke-width: 1.5;\n stroke-linecap: round;\n stroke-linejoin: round;\n}\nnav button[aria-selected='true'] {\n background: var(--office-teams-brand-subtle);\n color: var(--office-teams-brand);\n font-weight: var(--office-font-weight-bold);\n}\n.settings-content {\n min-width: 0;\n min-height: 0;\n overflow: auto;\n overscroll-behavior: contain;\n}\nsection {\n padding: var(--office-space-5);\n}\nsection h3 {\n margin: var(--office-space-5) 0 var(--office-space-3);\n font-size: var(--office-font-size);\n}\nsection h2 + h3 {\n margin-top: var(--office-space-4);\n}\n[hidden] {\n display: none !important;\n}\n.description {\n color: var(--office-teams-text-subtle);\n line-height: 1.5;\n}\noffice-ui-switch {\n --office-switch-track-on: var(--office-teams-brand);\n}\n.preference {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding-block: var(--office-space-3);\n border-block-end: var(--office-border-width) solid var(--office-teams-divider);\n font-weight: normal;\n}\nh2 {\n position: sticky;\n top: 0;\n z-index: 1;\n margin: calc(-1 * var(--office-space-5)) calc(-1 * var(--office-space-5)) var(--office-space-4);\n padding: var(--office-space-5);\n background: var(--office-popover);\n border-bottom: var(--office-border-width) solid var(--office-teams-divider);\n font-size: var(--office-font-size-lg);\n}\nlabel {\n display: grid;\n gap: var(--office-space-1);\n font-weight: var(--office-font-weight-bold);\n}\nsmall {\n color: var(--office-teams-text-subtle);\n font-weight: normal;\n}\ninput,\ntextarea,\nselect {\n padding: var(--office-space-2);\n border: var(--office-border-width) solid var(--office-field-border);\n border-radius: var(--office-radius);\n background: var(--office-field-background);\n color: inherit;\n font: inherit;\n}\ntextarea {\n min-height: 5.5em;\n font-family: ui-monospace, monospace;\n font-size: 0.9em;\n}\n.issues {\n margin: 0;\n padding-inline-start: 1.2em;\n color: var(--office-danger);\n font-size: var(--office-font-size-sm);\n}\n.actions {\n display: flex;\n justify-content: flex-end;\n gap: var(--office-space-2);\n}\nbutton {\n padding: var(--office-space-2) var(--office-space-4);\n border: var(--office-border-width) solid var(--office-teams-divider);\n border-radius: var(--office-radius-md);\n background: var(--office-background);\n color: inherit;\n font: inherit;\n cursor: pointer;\n}\nbutton.primary {\n border-color: transparent;\n background: var(--office-teams-brand);\n color: var(--office-teams-brand-foreground);\n}\nbutton.primary:hover {\n background: var(--office-teams-brand-hover);\n}\n:focus-visible {\n outline: var(--office-focus-width) solid var(--office-ring);\n outline-offset: var(--office-focus-offset);\n}\n@media (max-width: 48em) {\n .settings-layout {\n grid-template-columns: minmax(0, 1fr);\n grid-template-rows: auto minmax(0, 1fr);\n min-height: 0;\n }\n nav {\n max-height: 30dvh;\n border-inline-end: 0;\n border-block-end: var(--office-border-width) solid var(--office-teams-divider);\n }\n}\n";
|
|
2791
|
+
var teams_settings_default = ":host {\n font: var(--office-font-size) var(--office-font);\n color: var(--office-foreground);\n}\ndialog {\n box-sizing: border-box;\n width: min(76em, 94vw);\n max-height: 90dvh;\n overflow: hidden;\n padding: 0;\n border: var(--office-border-width) solid var(--office-teams-divider);\n border-radius: var(--office-radius-lg);\n background: var(--office-popover);\n color: inherit;\n box-shadow: var(--office-shadow-teams);\n}\ndialog::backdrop {\n background: var(--office-overlay);\n}\n:host([embedded]) {\n display: block;\n height: 100%;\n min-height: 0;\n}\n:host([embedded]:not([open])) {\n display: none;\n}\n:host([embedded]) dialog {\n position: relative;\n width: 100%;\n height: 100%;\n max-width: none;\n max-height: none;\n margin: 0;\n border: 0;\n border-radius: 0;\n box-shadow: none;\n}\n:host([embedded]) dialog[open] {\n display: flex;\n flex-direction: column;\n}\n:host([embedded]) .settings-layout {\n flex: 1;\n height: auto;\n}\nform {\n display: grid;\n gap: var(--office-space-3);\n padding: var(--office-space-5);\n}\nheader {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: var(--office-space-4) var(--office-space-5);\n border-block-end: var(--office-border-width) solid var(--office-teams-divider);\n gap: var(--office-space-3);\n}\nheader input {\n margin-inline-start: auto;\n width: min(24em, 50%);\n min-width: 0;\n}\n.settings-results ul {\n list-style: none;\n padding: 0;\n display: grid;\n gap: var(--office-space-3);\n}\n.settings-results button {\n display: grid;\n gap: var(--office-space-2);\n width: 100%;\n text-align: start;\n}\n.settings-results button:hover {\n background: var(--office-selected);\n}\nh1 {\n margin: 0;\n font-size: var(--office-font-size-lg);\n}\n.settings-layout {\n display: grid;\n grid-template-columns: 19em minmax(0, 1fr);\n height: min(42em, calc(90dvh - 5em));\n min-height: 0;\n}\nnav {\n min-height: 0;\n overflow-y: auto;\n display: flex;\n flex-direction: column;\n gap: var(--office-space-1);\n padding: var(--office-space-3);\n background: var(--office-teams-panel);\n border-inline-end: var(--office-border-width) solid var(--office-teams-divider);\n}\nnav button {\n display: flex;\n align-items: center;\n gap: var(--office-space-3);\n min-height: 3em;\n text-align: start;\n border: 0;\n background: transparent;\n}\nnav button:hover {\n background: var(--office-selected);\n}\n.icon {\n width: 1.4em;\n height: 1.4em;\n flex-shrink: 0;\n fill: none;\n stroke: currentColor;\n stroke-width: 1.5;\n stroke-linecap: round;\n stroke-linejoin: round;\n}\nnav button[aria-selected='true'] {\n background: var(--office-teams-brand-subtle);\n color: var(--office-teams-brand);\n font-weight: var(--office-font-weight-bold);\n}\n.settings-content {\n min-width: 0;\n min-height: 0;\n overflow: auto;\n overscroll-behavior: contain;\n}\nsection {\n padding: var(--office-space-5);\n}\nsection h3 {\n margin: var(--office-space-5) 0 var(--office-space-3);\n font-size: var(--office-font-size);\n}\nsection h2 + h3 {\n margin-top: var(--office-space-4);\n}\n[hidden] {\n display: none !important;\n}\n.description {\n color: var(--office-teams-text-subtle);\n line-height: 1.5;\n}\noffice-ui-switch {\n --office-switch-track-on: var(--office-teams-brand);\n}\n.preference {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding-block: var(--office-space-3);\n border-block-end: var(--office-border-width) solid var(--office-teams-divider);\n font-weight: normal;\n}\nh2 {\n position: sticky;\n top: 0;\n z-index: 1;\n margin: calc(-1 * var(--office-space-5)) calc(-1 * var(--office-space-5)) var(--office-space-4);\n padding: var(--office-space-5);\n background: var(--office-popover);\n border-bottom: var(--office-border-width) solid var(--office-teams-divider);\n font-size: var(--office-font-size-lg);\n}\nlabel {\n display: grid;\n gap: var(--office-space-1);\n font-weight: var(--office-font-weight-bold);\n}\nsmall {\n color: var(--office-teams-text-subtle);\n font-weight: normal;\n}\ninput,\ntextarea,\nselect {\n padding: var(--office-space-2);\n border: var(--office-border-width) solid var(--office-field-border);\n border-radius: var(--office-radius);\n background: var(--office-field-background);\n color: inherit;\n font: inherit;\n}\ntextarea {\n min-height: 5.5em;\n font-family: ui-monospace, monospace;\n font-size: 0.9em;\n}\n.issues {\n margin: 0;\n padding-inline-start: 1.2em;\n color: var(--office-danger);\n font-size: var(--office-font-size-sm);\n}\n.actions {\n display: flex;\n justify-content: flex-end;\n gap: var(--office-space-2);\n}\nbutton {\n padding: var(--office-space-2) var(--office-space-4);\n border: var(--office-border-width) solid var(--office-teams-divider);\n border-radius: var(--office-radius-md);\n background: var(--office-background);\n color: inherit;\n font: inherit;\n cursor: pointer;\n}\nbutton.primary {\n border-color: transparent;\n background: var(--office-teams-brand);\n color: var(--office-teams-brand-foreground);\n}\nbutton.primary:hover {\n background: var(--office-teams-brand-hover);\n}\n:focus-visible {\n outline: var(--office-focus-width) solid var(--office-ring);\n outline-offset: var(--office-focus-offset);\n}\n@media (max-width: 48em) {\n .settings-layout {\n grid-template-columns: minmax(0, 1fr);\n grid-template-rows: auto minmax(0, 1fr);\n min-height: 0;\n }\n nav {\n max-height: 30dvh;\n border-inline-end: 0;\n border-block-end: var(--office-border-width) solid var(--office-teams-divider);\n }\n}\n\n.notification-level {\n display: grid;\n gap: var(--office-space-2);\n margin: var(--office-space-3) 0 0;\n padding: 0;\n border: 0;\n}\n.notification-level legend {\n margin-bottom: var(--office-space-2);\n padding: 0;\n font-weight: var(--office-font-weight-bold);\n}\n.notification-choice {\n display: flex;\n align-items: flex-start;\n gap: var(--office-space-3);\n padding: var(--office-space-2) var(--office-space-3);\n border: var(--office-border-width) solid var(--office-teams-divider);\n border-radius: var(--office-radius-md);\n cursor: pointer;\n font-weight: normal;\n}\n.notification-choice:has(input:checked) {\n border-color: var(--office-teams-brand);\n background: var(--office-teams-brand-subtle);\n}\n.notification-choice input {\n margin-block-start: var(--office-space-1);\n accent-color: var(--office-teams-brand);\n}\n.notification-choice span {\n display: grid;\n gap: var(--office-space-1);\n}\n.notification-choice small {\n color: var(--office-teams-text-subtle);\n}\n";
|
|
1933
2792
|
|
|
1934
2793
|
// raw-css:/home/runner/work/ooxml/ooxml/src/ui/src/teams/app/settings-previews.css?raw
|
|
1935
2794
|
var settings_previews_default = ".theme-options,\n.density-options {\n display: flex;\n flex-wrap: wrap;\n gap: var(--office-space-3);\n}\n.theme-options button {\n display: grid;\n gap: var(--office-space-3);\n padding: var(--office-space-2);\n text-align: start;\n min-width: 9em;\n}\n.theme-options button[aria-pressed='true'],\n.density-choice:has(input:checked) {\n border-color: var(--office-teams-brand);\n box-shadow: inset 0 0 0 var(--office-border-width) var(--office-teams-brand);\n}\n.theme-swatch {\n --preview-paper: var(--office-call-foreground);\n --preview-ink: var(--office-call-background);\n display: grid;\n grid-template-columns: 0.7em 2.4em 1fr;\n grid-template-rows: 0.7em 1fr;\n width: 9em;\n height: 5.5em;\n border: var(--office-border-width) solid var(--office-teams-divider);\n border-radius: var(--office-radius);\n overflow: hidden;\n background: var(--preview-paper);\n}\n.theme-swatch[data-theme='dark'] {\n --preview-paper: var(--office-call-background);\n --preview-ink: var(--office-call-foreground);\n}\n.theme-swatch[data-theme='system'] {\n background: linear-gradient(\n 90deg,\n var(--office-call-foreground) 50%,\n var(--office-call-background) 50%\n );\n}\n.preview-toolbar {\n grid-column: 1 / -1;\n background: var(--office-teams-brand);\n}\n.preview-rail,\n.preview-sidebar {\n background: color-mix(in srgb, var(--preview-ink) 8%, var(--preview-paper));\n border-inline-end: var(--office-border-width) solid var(--office-teams-divider);\n}\n.preview-sidebar,\n.preview-conversation {\n display: flex;\n flex-direction: column;\n gap: var(--office-space-2);\n padding: var(--office-space-2);\n}\n.preview-sidebar i,\n.preview-conversation i {\n height: 0.4em;\n border-radius: var(--office-radius);\n background: color-mix(in srgb, var(--preview-ink) 25%, var(--preview-paper));\n}\n.preview-conversation i {\n height: 0.8em;\n width: 80%;\n}\n.preview-conversation i:nth-child(2) {\n align-self: flex-end;\n background: var(--office-teams-brand-subtle);\n}\n.density-options {\n margin: var(--office-space-5) 0 0;\n padding: var(--office-space-5) 0 0;\n border: 0;\n border-top: var(--office-border-width) solid var(--office-teams-divider);\n}\n.density-options legend {\n float: inline-start;\n width: 100%;\n font-weight: var(--office-font-weight-bold);\n margin-bottom: var(--office-space-3);\n}\n.density-choice {\n position: relative;\n display: flex;\n flex-direction: column;\n gap: var(--office-space-3);\n width: 13em;\n padding: var(--office-space-2);\n border: var(--office-border-width) solid var(--office-teams-divider);\n border-radius: var(--office-radius-md);\n cursor: pointer;\n font-weight: normal;\n}\n.density-choice input {\n position: absolute;\n inset-inline-end: var(--office-space-2);\n inset-block-end: var(--office-space-2);\n accent-color: var(--office-teams-brand);\n}\n.density-caption {\n display: grid;\n gap: var(--office-space-1);\n padding-inline-end: var(--office-space-5);\n}\n.density-preview {\n display: flex;\n flex-direction: column;\n justify-content: center;\n gap: var(--office-space-3);\n height: 7em;\n padding: var(--office-space-3);\n border-radius: var(--office-radius);\n background: var(--office-teams-panel);\n}\n.preview-message {\n display: flex;\n gap: var(--office-space-2);\n align-items: flex-start;\n}\n.preview-message > i {\n width: 1.1em;\n height: 1.1em;\n border-radius: 50%;\n background: var(--office-teams-brand-subtle);\n border: var(--office-border-width) solid var(--office-teams-brand);\n}\n.preview-message > span {\n display: grid;\n gap: var(--office-space-1);\n flex: 1;\n}\n.preview-message b {\n height: 0.3em;\n width: 75%;\n background: var(--office-teams-text-subtle);\n border-radius: var(--office-radius);\n}\n.preview-message b + b {\n width: 100%;\n opacity: 0.4;\n}\n.density-preview[data-density='compact'] {\n gap: var(--office-space-1);\n}\n.density-preview[data-density='compact'] .preview-message > i {\n width: 0.7em;\n height: 0.7em;\n}\n.density-preview[data-density='compact'] .preview-message > span {\n display: flex;\n align-items: center;\n}\n@media (forced-colors: active) {\n .theme-options button[aria-pressed='true'],\n .density-choice:has(input:checked) {\n outline: var(--office-focus-width) solid Highlight;\n }\n}\n";
|
|
@@ -1998,6 +2857,53 @@ function densityChoices(density, change) {
|
|
|
1998
2857
|
)}
|
|
1999
2858
|
</fieldset>`;
|
|
2000
2859
|
}
|
|
2860
|
+
var LEVELS = [
|
|
2861
|
+
["all", "All activity", "Mentions, replies, reactions and pinned messages"],
|
|
2862
|
+
["mentions", "Mentions only", "Only when someone mentions you"],
|
|
2863
|
+
["off", "Off", "Activity still collects in the Activity feed"]
|
|
2864
|
+
];
|
|
2865
|
+
var PERMISSION_TEXT = {
|
|
2866
|
+
granted: "Desktop notifications are on for this browser. They appear when this tab is in the background.",
|
|
2867
|
+
default: "Desktop notifications appear when this tab is in the background. Your browser asks first.",
|
|
2868
|
+
denied: "Desktop notifications are blocked for this site. Allow them in your browser settings to turn them on.",
|
|
2869
|
+
unsupported: "This browser does not support desktop notifications."
|
|
2870
|
+
};
|
|
2871
|
+
var desktopPermission = () => globalThis.Notification?.permission ?? "unsupported";
|
|
2872
|
+
function notificationChoices(settings, permission, handlers) {
|
|
2873
|
+
return html`<fieldset class="notification-level">
|
|
2874
|
+
<legend>Notify me about</legend>
|
|
2875
|
+
${LEVELS.map(
|
|
2876
|
+
([level, label, description]) => html`<label class="notification-choice">
|
|
2877
|
+
<input
|
|
2878
|
+
type="radio"
|
|
2879
|
+
name="notification-level"
|
|
2880
|
+
value=${level}
|
|
2881
|
+
.checked=${settings.level === level}
|
|
2882
|
+
@change=${() => handlers.change({ level })}
|
|
2883
|
+
/>
|
|
2884
|
+
<span><strong>${label}</strong><small>${description}</small></span>
|
|
2885
|
+
</label>`
|
|
2886
|
+
)}
|
|
2887
|
+
</fieldset>
|
|
2888
|
+
<h3>Sound</h3>
|
|
2889
|
+
<label class="preference"
|
|
2890
|
+
><span>Play a sound for new notifications</span
|
|
2891
|
+
><office-ui-switch
|
|
2892
|
+
aria-label="Notification sound"
|
|
2893
|
+
.checked=${settings.sound}
|
|
2894
|
+
@change=${(event) => handlers.change({ sound: event.target.checked })}
|
|
2895
|
+
></office-ui-switch
|
|
2896
|
+
></label>
|
|
2897
|
+
<h3>Desktop notifications</h3>
|
|
2898
|
+
<p class="description" role="status">${PERMISSION_TEXT[permission]}</p>
|
|
2899
|
+
${permission === "default" ? html`<button type="button" class="primary" @click=${handlers.requestPermission}>
|
|
2900
|
+
Enable desktop notifications
|
|
2901
|
+
</button>` : ""}
|
|
2902
|
+
<p class="description">
|
|
2903
|
+
Do not disturb silences every notification. Email and mobile push notifications are not
|
|
2904
|
+
available.
|
|
2905
|
+
</p>`;
|
|
2906
|
+
}
|
|
2001
2907
|
var SETTINGS_CATEGORIES = [
|
|
2002
2908
|
["general", "General"],
|
|
2003
2909
|
["appearance", "Appearance and accessibility"],
|
|
@@ -2022,6 +2928,21 @@ var TOPICS = [
|
|
|
2022
2928
|
title: "Show app names",
|
|
2023
2929
|
description: "Display labels beneath app bar icons"
|
|
2024
2930
|
},
|
|
2931
|
+
{
|
|
2932
|
+
category: "notifications",
|
|
2933
|
+
title: "Activity notifications",
|
|
2934
|
+
description: "Notify for all activity, mentions only or nothing"
|
|
2935
|
+
},
|
|
2936
|
+
{
|
|
2937
|
+
category: "notifications",
|
|
2938
|
+
title: "Sound",
|
|
2939
|
+
description: "Play a sound for new notifications"
|
|
2940
|
+
},
|
|
2941
|
+
{
|
|
2942
|
+
category: "notifications",
|
|
2943
|
+
title: "Desktop notifications",
|
|
2944
|
+
description: "Browser notifications while this tab is in the background, and Do not disturb"
|
|
2945
|
+
},
|
|
2025
2946
|
{
|
|
2026
2947
|
category: "notifications",
|
|
2027
2948
|
title: "Followed threads",
|
|
@@ -2075,6 +2996,7 @@ var TeamsSettings = class extends LitElement {
|
|
|
2075
2996
|
category: { state: true },
|
|
2076
2997
|
theme: { attribute: false },
|
|
2077
2998
|
followSettings: { attribute: false },
|
|
2999
|
+
notificationSettings: { attribute: false },
|
|
2078
3000
|
userName: { attribute: false },
|
|
2079
3001
|
fileOpenPreference: { attribute: false },
|
|
2080
3002
|
chatDensity: { attribute: false },
|
|
@@ -2090,6 +3012,7 @@ var TeamsSettings = class extends LitElement {
|
|
|
2090
3012
|
this.category = "general";
|
|
2091
3013
|
this.theme = "system";
|
|
2092
3014
|
this.followSettings = { started: true, replied: true };
|
|
3015
|
+
this.notificationSettings = { level: "all", sound: true };
|
|
2093
3016
|
this.userName = "";
|
|
2094
3017
|
this.fileOpenPreference = "teams";
|
|
2095
3018
|
this.chatDensity = "comfy";
|
|
@@ -2279,12 +3202,22 @@ var TeamsSettings = class extends LitElement {
|
|
|
2279
3202
|
?hidden=${!!this.query.trim() || this.category !== "notifications"}
|
|
2280
3203
|
>
|
|
2281
3204
|
<h2>Notifications and activity</h2>
|
|
3205
|
+
<h3>Activity notifications</h3>
|
|
3206
|
+
${notificationChoices(this.notificationSettings, desktopPermission(), {
|
|
3207
|
+
change: (detail) => this.dispatchEvent(
|
|
3208
|
+
new CustomEvent("teams-settings-notifications", {
|
|
3209
|
+
detail,
|
|
3210
|
+
bubbles: true,
|
|
3211
|
+
composed: true
|
|
3212
|
+
})
|
|
3213
|
+
),
|
|
3214
|
+
requestPermission: () => void globalThis.Notification?.requestPermission().then(
|
|
3215
|
+
() => this.requestUpdate()
|
|
3216
|
+
)
|
|
3217
|
+
})}
|
|
2282
3218
|
<h3>Followed threads</h3>
|
|
2283
3219
|
<p class="description">Choose which conversations appear in Followed threads.</p>
|
|
2284
3220
|
${["started", "replied"].map((key) => html`<label class="preference"><span>${key === "started" ? "Threads I start" : "Threads I reply to"}</span><office-ui-switch aria-label=${key === "started" ? "Threads I start" : "Threads I reply to"} .checked=${this.followSettings[key]} @change=${(event) => this.dispatchEvent(new CustomEvent("teams-settings-follow", { detail: { [key]: event.target.checked }, bubbles: true, composed: true }))}></office-ui-switch></label>`)}
|
|
2285
|
-
<p class="description">
|
|
2286
|
-
Desktop, email and activity notifications are not available yet.
|
|
2287
|
-
</p>
|
|
2288
3221
|
</section>
|
|
2289
3222
|
<section
|
|
2290
3223
|
id="panel-files"
|
|
@@ -2439,8 +3372,8 @@ function loadConfig() {
|
|
|
2439
3372
|
var saveConfig = (config) => safeStorage.setItem("teams:config", JSON.stringify(config));
|
|
2440
3373
|
|
|
2441
3374
|
// raw-css:/home/runner/work/ooxml/ooxml/src/ui/src/teams/app/teams-app.css?raw
|
|
2442
|
-
var teams_app_default = "/* <teams-app>: the shell. Colours, spacing and radii come from the ooxml-ui tokens, so a host\n retheme or dark mode reaches the whole app. The elements inside bring their own styles. */\n:host {\n display: block;\n height: 100%;\n min-height: 28em;\n font: var(--office-font-size) var(--office-font);\n color: var(--office-foreground);\n background: var(--office-background);\n}\n:host([data-office-theme='dark']) {\n --office-background: var(--office-teams-panel);\n --office-surface: var(--office-teams-bubble);\n --office-popover: var(--office-teams-panel);\n}\n:host([data-chat-density='compact']) {\n --office-teams-message-gap: var(--office-space-1);\n --office-teams-message-padding: var(--office-space-1) var(--office-space-2);\n}\n@media (prefers-color-scheme: dark) {\n :host(:not([data-office-theme='light'])) {\n --office-background: var(--office-teams-panel);\n --office-surface: var(--office-teams-bubble);\n --office-popover: var(--office-teams-panel);\n }\n}\n*,\n*::before,\n*::after {\n box-sizing: border-box;\n}\nbutton {\n font: inherit;\n color: inherit;\n cursor: pointer;\n}\n:focus-visible {\n outline: var(--office-focus-width) solid var(--office-ring);\n outline-offset: var(--office-focus-offset);\n}\n\n.shell {\n display: grid;\n grid-template-rows: auto minmax(0, 1fr);\n height: 100%;\n}\n\n/* ---- top bar ---------------------------------------------------------------------------- */\n.topbar {\n display: grid;\n grid-template-columns: 16em minmax(0, 1fr) auto;\n align-items: center;\n gap: var(--office-space-4);\n padding: var(--office-space-2) var(--office-space-4);\n background: var(--office-teams-rail);\n border-bottom: var(--office-border-width) solid var(--office-teams-divider);\n}\n.navigation-toggle {\n display: none;\n padding: var(--office-space-2);\n border: 0;\n border-radius: var(--office-radius-md);\n background: transparent;\n}\n.navigation-toggle:hover {\n background: var(--office-selected);\n}\n.navigation-toggle svg {\n width: 1.3em;\n height: 1.3em;\n fill: none;\n stroke: currentColor;\n stroke-width: var(--office-icon-stroke);\n stroke-linecap: round;\n}\n.brand {\n display: flex;\n align-items: center;\n gap: var(--office-space-2);\n font-size: var(--office-font-size-lg);\n font-weight: var(--office-font-weight-bold);\n}\n.logo {\n display: inline-grid;\n place-items: center;\n width: 1.8em;\n height: 1.8em;\n border-radius: var(--office-radius-md);\n background: var(--office-teams-brand);\n color: var(--office-teams-brand-foreground);\n font-size: 0.85em;\n}\n.search {\n position: relative;\n justify-self: center;\n width: min(34em, 100%);\n}\n.search input {\n width: 100%;\n padding: var(--office-space-2) var(--office-space-4);\n border: var(--office-border-width) solid var(--office-teams-divider);\n border-radius: var(--office-radius-full);\n background: var(--office-background);\n color: inherit;\n font: inherit;\n}\n.results {\n position: absolute;\n inset-inline: 0;\n inset-block-start: calc(100% + var(--office-space-1));\n z-index: 5;\n max-height: 22em;\n margin: 0;\n padding: var(--office-space-1);\n overflow: auto;\n list-style: none;\n border: var(--office-border-width) solid var(--office-teams-divider);\n border-radius: var(--office-radius-md);\n background: var(--office-popover);\n box-shadow: var(--office-shadow-teams);\n}\n.results button {\n display: grid;\n width: 100%;\n padding: var(--office-space-2) var(--office-space-3);\n border: 0;\n border-radius: var(--office-radius);\n background: transparent;\n text-align: start;\n}\n.results button:hover {\n background: var(--office-selected);\n}\n.results .in,\n.results .none {\n color: var(--office-teams-text-subtle);\n font-size: var(--office-font-size-sm);\n}\n.results .none {\n padding: var(--office-space-3);\n}\n.snippet {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.me {\n display: flex;\n align-items: center;\n gap: var(--office-space-3);\n}\n.me office-ui-menu-button::part(caret) {\n display: none;\n}\n.channel-head office-ui-menu-button::part(caret) {\n display: none;\n}\n.channel-head svg {\n width: 1em;\n height: 1em;\n fill: none;\n stroke: currentColor;\n stroke-width: var(--office-icon-stroke);\n stroke-linecap: round;\n stroke-linejoin: round;\n}\n\n/* ---- body ------------------------------------------------------------------------------- */\n.body {\n display: grid;\n grid-template-columns: auto 19em minmax(0, 1fr);\n min-height: 0;\n grid-template-rows: minmax(0, 1fr);\n}\n.body > office-ui-app-rail {\n grid-column: 1;\n grid-row: 1;\n}\n.body > .side {\n grid-column: 2;\n grid-row: 1;\n}\n.body > .main {\n grid-column: 3;\n grid-row: 1;\n}\n.body > teams-settings {\n grid-column: 2 / -1;\n grid-row: 1;\n min-width: 0;\n min-height: 0;\n z-index: 1;\n}\n.body > teams-settings:not([open]) {\n display: none;\n}\n.body > [inert] {\n visibility: hidden;\n}\n.side {\n min-height: 0;\n overflow: auto;\n background: var(--office-teams-panel);\n border-inline-end: var(--office-border-width) solid var(--office-teams-divider);\n}\n.side h2 {\n margin: 0;\n padding: var(--office-space-3) var(--office-space-4);\n font-size: var(--office-font-size-lg);\n}\n.main {\n display: flex;\n flex-direction: column;\n min-width: 0;\n min-height: 0;\n}\n.popout-view {\n display: flex;\n height: 100%;\n min-height: 0;\n}\n.popout-view teams-content-preview {\n flex: 1;\n}\n.main office-ui-chat-list,\n.main office-ui-prejoin {\n flex: 1;\n}\n\nul.plain {\n margin: 0;\n padding: 0 var(--office-space-3);\n list-style: none;\n}\nul.plain li {\n display: flex;\n align-items: center;\n gap: var(--office-space-2);\n padding: var(--office-space-2) var(--office-space-2);\n}\nul.plain li > :first-child:not(office-ui-avatar) {\n flex: 1;\n}\n.hint {\n padding: 0 var(--office-space-4);\n color: var(--office-teams-text-subtle);\n}\n.join {\n padding: var(--office-space-1) var(--office-space-3);\n border: var(--office-border-width) solid var(--office-teams-divider);\n border-radius: var(--office-radius-md);\n background: var(--office-background);\n}\n.join.live {\n border-color: transparent;\n background: var(--office-call-live);\n color: var(--office-call-foreground);\n}\n\n/* ---- conversation ----------------------------------------------------------------------- */\n.channel-head {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--office-space-4);\n padding: var(--office-space-2) var(--office-space-5);\n border-bottom: var(--office-border-width) solid var(--office-teams-divider);\n}\n.channel-head > button:not(.meet),\n.thread-head button {\n padding: var(--office-space-2) var(--office-space-3);\n border: var(--office-border-width) solid var(--office-teams-divider);\n border-radius: var(--office-radius-md);\n background: var(--office-background);\n}\n.channel-head > button:hover:not(:disabled),\n.thread-head button:hover {\n background: var(--office-selected);\n}\n.channel-head > button:disabled {\n opacity: 0.5;\n cursor: default;\n}\n.channel-head h1 {\n margin: 0;\n font-size: var(--office-font-size-lg);\n white-space: nowrap;\n}\n.hash {\n color: var(--office-teams-text-subtle);\n}\n.tabs {\n display: flex;\n gap: var(--office-space-1);\n}\n.tabs button {\n padding: var(--office-space-2) var(--office-space-3);\n border: 0;\n border-bottom: var(--office-border-width-thick) solid transparent;\n background: transparent;\n}\n.tabs button[aria-selected='true'] {\n border-bottom-color: var(--office-teams-brand);\n font-weight: var(--office-font-weight-bold);\n}\n.topic {\n flex: 1;\n min-width: 0;\n overflow: hidden;\n color: var(--office-teams-text-subtle);\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.people {\n display: flex;\n align-items: center;\n gap: var(--office-space-0);\n}\n.more {\n margin-inline-start: var(--office-space-1);\n color: var(--office-teams-text-subtle);\n font-size: var(--office-font-size-sm);\n}\n.meet {\n padding: var(--office-space-2) var(--office-space-4);\n border: 0;\n border-radius: var(--office-radius-md);\n background: var(--office-teams-brand);\n color: var(--office-teams-brand-foreground);\n font-weight: var(--office-font-weight-bold);\n}\n.meet:hover:not(:disabled) {\n background: var(--office-teams-brand-hover);\n}\n.meet:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n.callbar {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: var(--office-space-2) var(--office-space-5);\n background: var(--office-call-live);\n color: var(--office-call-foreground);\n}\n.callbar button {\n padding: 0 var(--office-space-3);\n border: var(--office-border-width) solid currentColor;\n border-radius: var(--office-radius);\n background: transparent;\n}\n\n/* ---- files ------------------------------------------------------------------------------ */\n/* ---- meeting ---------------------------------------------------------------------------- */\n.meeting {\n display: grid;\n grid-template-rows: auto minmax(0, 1fr);\n height: 100%;\n background: var(--office-call-background);\n}\n.stage {\n display: grid;\n grid-template-columns: minmax(0, 1fr) auto;\n min-height: 0;\n}\n.panel {\n display: flex;\n flex-direction: column;\n width: 22em;\n min-height: 0;\n background: var(--office-background);\n border-inline-start: var(--office-border-width) solid var(--office-teams-divider);\n}\n.panel office-ui-chat-list {\n flex: 1;\n padding-inline: var(--office-space-3);\n}\n.panel office-ui-chat-composer {\n padding-inline: var(--office-space-3);\n}\n.people-panel h2 {\n margin: 0;\n padding: var(--office-space-3) var(--office-space-4);\n font-size: var(--office-font-size-lg);\n}\n\n/* ---- welcome and toast ------------------------------------------------------------------ */\n.welcome {\n display: grid;\n place-items: center;\n height: 100%;\n background: var(--office-teams-panel);\n}\n.welcome form {\n display: grid;\n justify-items: center;\n gap: var(--office-space-3);\n width: min(24em, 90%);\n padding: var(--office-space-6);\n border-radius: var(--office-radius-lg);\n background: var(--office-background);\n box-shadow: var(--office-shadow-teams);\n}\n.welcome h1 {\n margin: 0;\n font-size: var(--office-font-size-xl);\n}\n.welcome p {\n margin: 0;\n color: var(--office-teams-text-subtle);\n}\n.welcome input {\n width: 100%;\n padding: var(--office-space-3);\n border: var(--office-border-width) solid var(--office-field-border);\n border-radius: var(--office-radius);\n background: var(--office-field-background);\n color: inherit;\n font: inherit;\n}\n.welcome button {\n width: 100%;\n padding: var(--office-space-3);\n border: 0;\n border-radius: var(--office-radius-md);\n background: var(--office-teams-brand);\n color: var(--office-teams-brand-foreground);\n font-weight: var(--office-font-weight-bold);\n}\n.toast {\n position: fixed;\n inset-block-end: var(--office-space-4);\n inset-inline-start: 50%;\n z-index: 10;\n transform: translateX(-50%);\n padding: var(--office-space-2) var(--office-space-4);\n border-radius: var(--office-radius-md);\n background: var(--office-call-background);\n color: var(--office-call-foreground);\n}\n\n.conversation-grid {\n display: grid;\n grid-template-columns: minmax(0, 1fr);\n flex: 1;\n min-height: 0;\n}\n.conversation-grid[data-thread='true'] {\n grid-template-columns: minmax(0, 1fr) minmax(18em, 0.8fr);\n}\n.conversation-main,\n.thread-pane {\n display: flex;\n flex-direction: column;\n min-height: 0;\n min-width: 0;\n}\n.tab-conversation teams-channel-tab {\n flex: 1;\n min-height: 0;\n}\n.thread-pane {\n border-inline-start: var(--office-border-width) solid var(--office-teams-divider);\n}\n.thread-head {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--office-space-3);\n padding: var(--office-space-3);\n}\n.thread-head h2 {\n margin: 0;\n font-size: 1em;\n}\n.followed-threads {\n overflow: auto;\n padding: var(--office-space-4);\n}\n.message-transfer {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--office-space-3);\n padding: var(--office-space-3);\n background: var(--office-teams-panel);\n border-block-end: var(--office-border-width) solid var(--office-teams-divider);\n}\n.message-transfer span {\n flex: 1;\n overflow-wrap: anywhere;\n}\n.message-transfer button {\n font: inherit;\n color: inherit;\n background: var(--office-background);\n border: var(--office-border-width) solid var(--office-teams-divider);\n border-radius: var(--office-radius-md);\n padding: var(--office-space-2) var(--office-space-3);\n cursor: pointer;\n}\n.followed-threads ul {\n list-style: none;\n padding: 0;\n}\n.followed-threads fieldset {\n display: flex;\n flex-wrap: wrap;\n gap: var(--office-space-4);\n padding: var(--office-space-3);\n margin-block: var(--office-space-3);\n border: var(--office-border-width) solid var(--office-teams-divider);\n border-radius: var(--office-radius-md);\n}\n.followed-threads li {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--office-space-3);\n padding-block: var(--office-space-3);\n border-block-end: var(--office-border-width) solid var(--office-teams-divider);\n}\n.followed-threads button {\n font: inherit;\n color: inherit;\n background: var(--office-background);\n border: var(--office-border-width) solid var(--office-teams-divider);\n border-radius: var(--office-radius-md);\n padding: var(--office-space-2) var(--office-space-3);\n cursor: pointer;\n}\n.followed-threads button:hover {\n background: var(--office-selected);\n}\n.followed-threads li button:first-child {\n display: grid;\n gap: var(--office-space-2);\n flex: 1;\n text-align: start;\n min-width: 0;\n overflow-wrap: anywhere;\n border-color: transparent;\n}\n.followed-threads li[data-unread='true'] button:first-child span {\n font-weight: var(--office-font-weight-bold);\n}\n@media (max-width: 56em) {\n .conversation-grid[data-thread='true'] {\n grid-template-columns: minmax(0, 1fr);\n }\n .conversation-grid[data-thread='true'] .conversation-main {\n display: none;\n }\n}\n.tabs {\n overflow-x: auto;\n min-width: 0;\n flex: 1 1 16em;\n}\n\n@media (max-width: 56.25em) {\n .navigation-toggle {\n display: inline-flex;\n }\n .brand > .logo,\n .brand > span:last-child {\n display: none;\n }\n .channel-head .topic,\n .channel-head .people {\n display: none;\n }\n .channel-head .tabs {\n flex-basis: 100%;\n }\n .body {\n grid-template-columns: auto minmax(0, 1fr);\n }\n .body > .main {\n grid-column: 2;\n }\n .side {\n display: none;\n }\n .topbar {\n grid-template-columns: auto minmax(0, 1fr) auto;\n }\n}\n\n/* An application host can own the single suite-level account control. */\n:host([host-profile]) teams-profile-menu {\n display: none;\n}\n";
|
|
2443
|
-
function threadPane(state, client, openFile, close) {
|
|
3375
|
+
var teams_app_default = "/* <teams-app>: the shell. Colours, spacing and radii come from the ooxml-ui tokens, so a host\n retheme or dark mode reaches the whole app. The elements inside bring their own styles. */\n:host {\n display: block;\n height: 100%;\n min-height: 28em;\n font: var(--office-font-size) var(--office-font);\n color: var(--office-foreground);\n background: var(--office-background);\n}\n:host([data-office-theme='dark']) {\n --office-background: var(--office-teams-panel);\n --office-surface: var(--office-teams-bubble);\n --office-popover: var(--office-teams-panel);\n}\n:host([data-chat-density='compact']) {\n --office-teams-message-gap: var(--office-space-1);\n --office-teams-message-padding: var(--office-space-1) var(--office-space-2);\n}\n@media (prefers-color-scheme: dark) {\n :host(:not([data-office-theme='light'])) {\n --office-background: var(--office-teams-panel);\n --office-surface: var(--office-teams-bubble);\n --office-popover: var(--office-teams-panel);\n }\n}\n*,\n*::before,\n*::after {\n box-sizing: border-box;\n}\nbutton {\n font: inherit;\n color: inherit;\n cursor: pointer;\n}\n:focus-visible {\n outline: var(--office-focus-width) solid var(--office-ring);\n outline-offset: var(--office-focus-offset);\n}\n\n.shell {\n display: grid;\n grid-template-rows: auto minmax(0, 1fr);\n height: 100%;\n}\n\n/* ---- top bar ---------------------------------------------------------------------------- */\n.topbar {\n display: grid;\n grid-template-columns: 16em minmax(0, 1fr) auto;\n align-items: center;\n gap: var(--office-space-4);\n padding: var(--office-space-2) var(--office-space-4);\n background: var(--office-teams-rail);\n border-bottom: var(--office-border-width) solid var(--office-teams-divider);\n}\n.brand {\n display: flex;\n align-items: center;\n gap: var(--office-space-2);\n font-size: var(--office-font-size-lg);\n font-weight: var(--office-font-weight-bold);\n}\n.logo {\n display: inline-grid;\n place-items: center;\n width: 1.8em;\n height: 1.8em;\n border-radius: var(--office-radius-md);\n background: var(--office-teams-brand);\n color: var(--office-teams-brand-foreground);\n font-size: 0.85em;\n}\n.search {\n position: relative;\n justify-self: center;\n width: min(34em, 100%);\n}\n.search input {\n width: 100%;\n padding: var(--office-space-2) var(--office-space-4);\n border: var(--office-border-width) solid var(--office-teams-divider);\n border-radius: var(--office-radius-full);\n background: var(--office-background);\n color: inherit;\n font: inherit;\n}\n.results {\n position: absolute;\n inset-inline: 0;\n inset-block-start: calc(100% + var(--office-space-1));\n z-index: 5;\n max-height: 22em;\n margin: 0;\n padding: var(--office-space-1);\n overflow: auto;\n list-style: none;\n border: var(--office-border-width) solid var(--office-teams-divider);\n border-radius: var(--office-radius-md);\n background: var(--office-popover);\n box-shadow: var(--office-shadow-teams);\n}\n.results button {\n display: grid;\n width: 100%;\n padding: var(--office-space-2) var(--office-space-3);\n border: 0;\n border-radius: var(--office-radius);\n background: transparent;\n text-align: start;\n}\n.results button:hover {\n background: var(--office-selected);\n}\n.results .in,\n.results .none {\n color: var(--office-teams-text-subtle);\n font-size: var(--office-font-size-sm);\n}\n.results .none {\n padding: var(--office-space-3);\n}\n.snippet {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.me {\n display: flex;\n align-items: center;\n gap: var(--office-space-3);\n}\n.me office-ui-menu-button::part(caret) {\n display: none;\n}\n.channel-head office-ui-menu-button::part(caret) {\n display: none;\n}\n.channel-head svg {\n width: 1em;\n height: 1em;\n fill: none;\n stroke: currentColor;\n stroke-width: var(--office-icon-stroke);\n stroke-linecap: round;\n stroke-linejoin: round;\n}\n\n/* ---- body ------------------------------------------------------------------------------- */\n.body {\n display: grid;\n grid-template-columns: auto 19em minmax(0, 1fr);\n min-height: 0;\n grid-template-rows: minmax(0, 1fr);\n}\n.body > office-ui-app-rail {\n grid-column: 1;\n grid-row: 1;\n}\n.body > .side {\n grid-column: 2;\n grid-row: 1;\n}\n.body > .main {\n grid-column: 3;\n grid-row: 1;\n}\n.body > teams-settings {\n grid-column: 2 / -1;\n grid-row: 1;\n min-width: 0;\n min-height: 0;\n z-index: 1;\n}\n.body > teams-settings:not([open]) {\n display: none;\n}\n.body > [inert] {\n visibility: hidden;\n}\n.side {\n min-height: 0;\n overflow: auto;\n background: var(--office-teams-panel);\n border-inline-end: var(--office-border-width) solid var(--office-teams-divider);\n}\n.side h2 {\n margin: 0;\n padding: var(--office-space-3) var(--office-space-4);\n font-size: var(--office-font-size-lg);\n}\n.main {\n display: flex;\n flex-direction: column;\n min-width: 0;\n min-height: 0;\n}\n.popout-view {\n display: flex;\n height: 100%;\n min-height: 0;\n}\n.popout-view teams-content-preview {\n flex: 1;\n}\n.main office-ui-chat-list,\n.main office-ui-prejoin {\n flex: 1;\n}\n\nul.plain {\n margin: 0;\n padding: 0 var(--office-space-3);\n list-style: none;\n}\nul.plain li {\n display: flex;\n align-items: center;\n gap: var(--office-space-2);\n padding: var(--office-space-2) var(--office-space-2);\n}\nul.plain li > :first-child:not(office-ui-avatar) {\n flex: 1;\n}\n.hint {\n padding: 0 var(--office-space-4);\n color: var(--office-teams-text-subtle);\n}\n.join {\n padding: var(--office-space-1) var(--office-space-3);\n border: var(--office-border-width) solid var(--office-teams-divider);\n border-radius: var(--office-radius-md);\n background: var(--office-background);\n}\n.join.live {\n border-color: transparent;\n background: var(--office-call-live);\n color: var(--office-call-foreground);\n}\n\n/* ---- conversation ----------------------------------------------------------------------- */\n.channel-head {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--office-space-4);\n padding: var(--office-space-2) var(--office-space-5);\n border-bottom: var(--office-border-width) solid var(--office-teams-divider);\n}\n.channel-head > button:not(.meet),\n.thread-head button {\n padding: var(--office-space-2) var(--office-space-3);\n border: var(--office-border-width) solid var(--office-teams-divider);\n border-radius: var(--office-radius-md);\n background: var(--office-background);\n}\n.channel-head > button:hover:not(:disabled),\n.thread-head button:hover {\n background: var(--office-selected);\n}\n.channel-head > button:disabled {\n opacity: 0.5;\n cursor: default;\n}\n.channel-head h1 {\n margin: 0;\n font-size: var(--office-font-size-lg);\n white-space: nowrap;\n}\n.hash {\n color: var(--office-teams-text-subtle);\n}\n.tabs {\n display: flex;\n gap: var(--office-space-1);\n}\n.tabs button {\n padding: var(--office-space-2) var(--office-space-3);\n border: 0;\n border-bottom: var(--office-border-width-thick) solid transparent;\n background: transparent;\n}\n.tabs button[aria-selected='true'] {\n border-bottom-color: var(--office-teams-brand);\n font-weight: var(--office-font-weight-bold);\n}\n.topic {\n flex: 1;\n min-width: 0;\n overflow: hidden;\n color: var(--office-teams-text-subtle);\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.people {\n display: flex;\n align-items: center;\n gap: var(--office-space-0);\n}\n.more {\n margin-inline-start: var(--office-space-1);\n color: var(--office-teams-text-subtle);\n font-size: var(--office-font-size-sm);\n}\n.meet {\n padding: var(--office-space-2) var(--office-space-4);\n border: 0;\n border-radius: var(--office-radius-md);\n background: var(--office-teams-brand);\n color: var(--office-teams-brand-foreground);\n font-weight: var(--office-font-weight-bold);\n}\n.meet:hover:not(:disabled) {\n background: var(--office-teams-brand-hover);\n}\n.meet:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n.callbar {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: var(--office-space-2) var(--office-space-5);\n background: var(--office-call-live);\n color: var(--office-call-foreground);\n}\n.callbar button {\n padding: 0 var(--office-space-3);\n border: var(--office-border-width) solid currentColor;\n border-radius: var(--office-radius);\n background: transparent;\n}\n\n/* ---- files ------------------------------------------------------------------------------ */\n/* ---- meeting ---------------------------------------------------------------------------- */\n.meeting {\n display: grid;\n grid-template-rows: auto minmax(0, 1fr);\n height: 100%;\n background: var(--office-call-background);\n}\n.stage {\n display: grid;\n grid-template-columns: minmax(0, 1fr) auto;\n min-height: 0;\n}\n.panel {\n display: flex;\n flex-direction: column;\n width: 22em;\n min-height: 0;\n background: var(--office-background);\n border-inline-start: var(--office-border-width) solid var(--office-teams-divider);\n}\n.panel office-ui-chat-list {\n flex: 1;\n padding-inline: var(--office-space-3);\n}\n.panel office-ui-chat-composer {\n padding-inline: var(--office-space-3);\n}\n.people-panel h2 {\n margin: 0;\n padding: var(--office-space-3) var(--office-space-4);\n font-size: var(--office-font-size-lg);\n}\n\n/* ---- welcome and toast ------------------------------------------------------------------ */\n.welcome {\n display: grid;\n place-items: center;\n height: 100%;\n background: var(--office-teams-panel);\n}\n.welcome form {\n display: grid;\n justify-items: center;\n gap: var(--office-space-3);\n width: min(24em, 90%);\n padding: var(--office-space-6);\n border-radius: var(--office-radius-lg);\n background: var(--office-background);\n box-shadow: var(--office-shadow-teams);\n}\n.welcome h1 {\n margin: 0;\n font-size: var(--office-font-size-xl);\n}\n.welcome p {\n margin: 0;\n color: var(--office-teams-text-subtle);\n}\n.welcome input {\n width: 100%;\n padding: var(--office-space-3);\n border: var(--office-border-width) solid var(--office-field-border);\n border-radius: var(--office-radius);\n background: var(--office-field-background);\n color: inherit;\n font: inherit;\n}\n.welcome button {\n width: 100%;\n padding: var(--office-space-3);\n border: 0;\n border-radius: var(--office-radius-md);\n background: var(--office-teams-brand);\n color: var(--office-teams-brand-foreground);\n font-weight: var(--office-font-weight-bold);\n}\n.toast {\n position: fixed;\n inset-block-end: var(--office-space-4);\n inset-inline-start: 50%;\n z-index: 10;\n transform: translateX(-50%);\n padding: var(--office-space-2) var(--office-space-4);\n border-radius: var(--office-radius-md);\n background: var(--office-call-background);\n color: var(--office-call-foreground);\n}\n\n.conversation-grid {\n display: grid;\n grid-template-columns: minmax(0, 1fr);\n flex: 1;\n min-height: 0;\n}\n.conversation-grid[data-thread='true'] {\n grid-template-columns: minmax(0, 1fr) minmax(18em, 0.8fr);\n}\n.conversation-main,\n.thread-pane {\n display: flex;\n flex-direction: column;\n min-height: 0;\n min-width: 0;\n}\n.tab-conversation teams-channel-tab {\n flex: 1;\n min-height: 0;\n}\n.thread-pane {\n border-inline-start: var(--office-border-width) solid var(--office-teams-divider);\n}\n.thread-head {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--office-space-3);\n padding: var(--office-space-3);\n}\n.thread-head h2 {\n margin: 0;\n font-size: 1em;\n}\n.followed-threads {\n overflow: auto;\n padding: var(--office-space-4);\n}\n.message-transfer {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--office-space-3);\n padding: var(--office-space-3);\n background: var(--office-teams-panel);\n border-block-end: var(--office-border-width) solid var(--office-teams-divider);\n}\n.message-transfer span {\n flex: 1;\n overflow-wrap: anywhere;\n}\n.message-transfer button {\n font: inherit;\n color: inherit;\n background: var(--office-background);\n border: var(--office-border-width) solid var(--office-teams-divider);\n border-radius: var(--office-radius-md);\n padding: var(--office-space-2) var(--office-space-3);\n cursor: pointer;\n}\n.followed-threads ul {\n list-style: none;\n padding: 0;\n}\n.followed-threads fieldset {\n display: flex;\n flex-wrap: wrap;\n gap: var(--office-space-4);\n padding: var(--office-space-3);\n margin-block: var(--office-space-3);\n border: var(--office-border-width) solid var(--office-teams-divider);\n border-radius: var(--office-radius-md);\n}\n.followed-threads li {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--office-space-3);\n padding-block: var(--office-space-3);\n border-block-end: var(--office-border-width) solid var(--office-teams-divider);\n}\n.followed-threads button {\n font: inherit;\n color: inherit;\n background: var(--office-background);\n border: var(--office-border-width) solid var(--office-teams-divider);\n border-radius: var(--office-radius-md);\n padding: var(--office-space-2) var(--office-space-3);\n cursor: pointer;\n}\n.followed-threads button:hover {\n background: var(--office-selected);\n}\n.followed-threads li button:first-child {\n display: grid;\n gap: var(--office-space-2);\n flex: 1;\n text-align: start;\n min-width: 0;\n overflow-wrap: anywhere;\n border-color: transparent;\n}\n.followed-threads li[data-unread='true'] button:first-child span {\n font-weight: var(--office-font-weight-bold);\n}\n@media (max-width: 56em) {\n .conversation-grid[data-thread='true'] {\n grid-template-columns: minmax(0, 1fr);\n }\n .conversation-grid[data-thread='true'] .conversation-main {\n display: none;\n }\n}\n.tabs {\n overflow-x: auto;\n min-width: 0;\n flex: 1 1 16em;\n}\n\n.channel-head > .back {\n display: none;\n}\n\n/* ---- compact shell ---------------------------------------------------------------------- */\n/* Below 56em the app rail is a bottom bar, the channel list is its own full-screen view and the\n conversation (or any other content) fills the width with a back button to the list. */\n@media (max-width: 56em) {\n .brand {\n display: none;\n }\n .topbar {\n grid-template-columns: minmax(0, 1fr) auto;\n gap: var(--office-space-2);\n }\n .search {\n width: 100%;\n }\n .channel-head {\n gap: var(--office-space-2);\n padding-inline: var(--office-space-3);\n }\n .channel-head > .back {\n display: inline-flex;\n border-color: transparent;\n }\n .channel-head .topic,\n .channel-head .people {\n display: none;\n }\n .channel-head .tabs {\n flex-basis: 100%;\n order: 1;\n }\n .body {\n grid-template-columns: minmax(0, 1fr);\n grid-template-rows: minmax(0, 1fr) auto;\n }\n .body > office-ui-app-rail {\n grid-column: 1;\n grid-row: 2;\n }\n .body > .side,\n .body > .main,\n .body > teams-settings {\n grid-column: 1;\n grid-row: 1;\n }\n .side {\n border-inline-end: 0;\n }\n .shell[data-mobile-view='list'] .main,\n .shell[data-mobile-view='content'] .side {\n display: none;\n }\n}\n/* Phone landscape has little height: keep the chrome to one thin row each. */\n@media (max-width: 56em) and (max-height: 30em) {\n .topbar {\n padding-block: var(--office-space-1);\n }\n .channel-head {\n flex-wrap: nowrap;\n padding-block: var(--office-space-1);\n }\n .channel-head .tabs {\n flex: 1 1 0;\n order: 0;\n }\n .channel-head h1 {\n font-size: var(--office-font-size);\n }\n}\n/* Touch: every control in the shell reaches the minimum hit target. */\n@media (pointer: coarse) {\n .channel-head > button,\n .meet,\n .tabs button,\n .join,\n .thread-head button,\n .callbar button {\n min-width: var(--office-touch-target, 44px);\n min-height: var(--office-touch-target, 44px);\n }\n}\n\n/* An application host can own the single suite-level account control. */\n:host([host-profile]) teams-profile-menu {\n display: none;\n}\n\n/* ---- activity ---------------------------------------------------------------------------- */\n.side > office-ui-activity-feed {\n height: 100%;\n}\n/* Toasts for new activity stack at the top right, under the header, so they never cover the\n compose box; on phones they are full-width banners below the header. */\n.activity-toasts {\n position: fixed;\n inset-block-start: 8em;\n inset-inline-end: var(--office-space-4);\n z-index: 10;\n display: flex;\n flex-direction: column;\n gap: var(--office-space-2);\n width: min(28em, calc(100% - var(--office-space-5)));\n pointer-events: none;\n}\n.activity-toast {\n display: flex;\n align-items: center;\n gap: var(--office-space-3);\n padding: var(--office-space-2) var(--office-space-3) var(--office-space-2) var(--office-space-4);\n border-radius: var(--office-radius-md);\n background: var(--office-call-background);\n color: var(--office-call-foreground);\n box-shadow: var(--office-shadow-teams);\n pointer-events: auto;\n}\n@media (max-width: 40em) {\n .activity-toasts {\n inset-block-start: 4.6em;\n inset-inline: var(--office-space-2);\n width: auto;\n }\n}\n.activity-toast .toast-text {\n display: flex;\n flex: 1;\n flex-direction: column;\n min-width: 0;\n}\n.activity-toast .toast-text > * {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.activity-toast .toast-preview {\n opacity: 0.8;\n font-size: var(--office-font-size-sm);\n}\n.activity-toast button {\n flex: none;\n padding: var(--office-space-1) var(--office-space-3);\n border: 0;\n border-radius: var(--office-radius);\n background: transparent;\n color: inherit;\n font-weight: var(--office-font-weight-bold);\n}\n.activity-toast button:hover {\n background: var(--office-selected);\n}\n.activity-toast button svg {\n width: 1em;\n height: 1em;\n fill: none;\n stroke: currentColor;\n stroke-width: var(--office-icon-stroke);\n stroke-linecap: round;\n stroke-linejoin: round;\n}\n@media (pointer: coarse) {\n .activity-toast button {\n min-width: var(--office-touch-target, 44px);\n min-height: var(--office-touch-target, 44px);\n }\n}\n\n/* ---- chat and calendar ------------------------------------------------------------------ */\n.calendar-back svg,\n.show-calendar svg,\n.group-mark svg,\n.chat-head .chat-people svg {\n width: 1.25em;\n height: 1.25em;\n flex: none;\n fill: none;\n stroke: currentColor;\n stroke-width: var(--office-icon-stroke);\n stroke-linecap: round;\n stroke-linejoin: round;\n}\n.chat-head office-ui-avatar {\n flex: none;\n}\n.group-mark {\n display: grid;\n flex: none;\n place-items: center;\n width: 2.3em;\n height: 2.3em;\n border-radius: var(--office-radius-full);\n background: var(--office-teams-bubble);\n color: var(--office-teams-brand);\n}\n.chat-head .chat-people {\n display: inline-flex;\n align-items: center;\n gap: var(--office-space-2);\n}\n.empty-main {\n display: grid;\n flex: 1;\n place-content: center;\n justify-items: center;\n gap: var(--office-space-3);\n padding: var(--office-space-6);\n color: var(--office-teams-text-subtle);\n text-align: center;\n}\n.empty-main button {\n padding: var(--office-space-2) var(--office-space-4);\n border: 0;\n border-radius: var(--office-radius-md);\n background: var(--office-teams-brand);\n color: var(--office-teams-brand-foreground);\n font: inherit;\n}\n.main > office-ui-calendar-view {\n flex: 1;\n min-height: 0;\n}\n.calendar-back {\n display: none;\n}\n@media (max-width: 56em) {\n .calendar-back {\n display: flex;\n align-items: center;\n gap: var(--office-space-2);\n padding: var(--office-space-2) var(--office-space-3);\n border-block-end: var(--office-border-width) solid var(--office-teams-divider);\n }\n .calendar-back button {\n display: inline-flex;\n align-items: center;\n gap: var(--office-space-2);\n min-height: var(--office-touch-target, 44px);\n padding: var(--office-space-2) var(--office-space-3);\n border: 0;\n border-radius: var(--office-radius-md);\n background: transparent;\n }\n .chat-head .chat-people {\n min-width: var(--office-touch-target, 44px);\n }\n}\n.show-calendar {\n display: none;\n}\n@media (max-width: 56em) {\n .show-calendar {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: var(--office-space-2);\n width: calc(100% - 2 * var(--office-space-4));\n min-height: var(--office-touch-target, 44px);\n margin: var(--office-space-3) var(--office-space-4);\n border: var(--office-border-width) solid var(--office-teams-divider);\n border-radius: var(--office-radius-md);\n background: var(--office-background);\n }\n}\n";
|
|
3376
|
+
function threadPane(state, client, openFile, close, highlightId = "") {
|
|
2444
3377
|
const thread = state.thread;
|
|
2445
3378
|
if (!thread) return nothing;
|
|
2446
3379
|
return html`<aside class="thread-pane" aria-label="Thread">
|
|
@@ -2456,7 +3389,11 @@ function threadPane(state, client, openFile, close) {
|
|
|
2456
3389
|
</header>
|
|
2457
3390
|
<office-ui-chat-list
|
|
2458
3391
|
.messages=${[thread.root, ...thread.replies]}
|
|
3392
|
+
.pinnedIds=${state.pinned.map((p) => p.message.id)}
|
|
2459
3393
|
self-id=${state.user.id}
|
|
3394
|
+
.highlightId=${highlightId}
|
|
3395
|
+
@office-chat-pin=${(e) => client.pinMessage(e.detail.messageId)}
|
|
3396
|
+
@office-chat-unpin=${(e) => client.unpinMessage(e.detail.messageId)}
|
|
2460
3397
|
@office-chat-react=${(e) => client.toggleReaction(e.detail.messageId, e.detail.emoji)}
|
|
2461
3398
|
@office-chat-reply=${(e) => client.startReply(e.detail.messageId)}
|
|
2462
3399
|
@office-chat-edit=${(e) => client.startEdit(e.detail.messageId)}
|
|
@@ -2470,6 +3407,7 @@ function threadPane(state, client, openFile, close) {
|
|
|
2470
3407
|
.value=${state.draft.text}
|
|
2471
3408
|
.files=${state.draft.files}
|
|
2472
3409
|
.missingFiles=${state.draft.missingFiles}
|
|
3410
|
+
.mentionTargets=${state.mentionTargets}
|
|
2473
3411
|
@office-chat-draft=${(e) => client.setDraft(e.detail)}
|
|
2474
3412
|
placeholder="Reply in thread"
|
|
2475
3413
|
@office-chat-typing=${() => client.notifyTyping()}
|
|
@@ -2486,7 +3424,10 @@ function followedThreads(state, client, open, unreadOnly, filter) {
|
|
|
2486
3424
|
const threads = state.followedThreads.filter((thread) => !unreadOnly || thread.unread > 0);
|
|
2487
3425
|
return html`<section class="followed-threads" aria-label="Followed threads">
|
|
2488
3426
|
<h1>Followed threads</h1>
|
|
2489
|
-
<p>
|
|
3427
|
+
<p>
|
|
3428
|
+
Threads you follow on this device. Their replies appear in Activity and notify you according
|
|
3429
|
+
to your notification settings.
|
|
3430
|
+
</p>
|
|
2490
3431
|
<fieldset>
|
|
2491
3432
|
<legend>Automatically follow</legend>
|
|
2492
3433
|
<label
|
|
@@ -2622,17 +3563,37 @@ function messageTransfers(state, client) {
|
|
|
2622
3563
|
}
|
|
2623
3564
|
|
|
2624
3565
|
// raw-css:/home/runner/work/ooxml/ooxml/src/ui/src/teams/app/profile-menu.css?raw
|
|
2625
|
-
var profile_menu_default = ":host {\n display: inline-flex;\n font: inherit;\n color: inherit;\n}\n.profile {\n display: inline-flex;\n align-items: center;\n padding: var(--office-space-1);\n border: 0;\n border-radius: var(--office-radius-full);\n background: transparent;\n cursor: pointer;\n}\n.profile:hover {\n background: var(--office-selected);\n}\n[popover] {\n min-width: 20em;\n max-width: 90vw;\n padding: var(--office-space-4);\n border: var(--office-border-width) solid var(--office-teams-divider);\n border-radius: var(--office-radius-md);\n background: var(--office-popover);\n color: var(--office-foreground);\n box-shadow: var(--office-shadow-teams);\n}\n.identity {\n display: flex;\n gap: var(--office-space-3);\n align-items: center;\n margin-bottom: var(--office-space-4);\n}\n.identity strong {\n overflow-wrap: anywhere;\n}\nlabel {\n display: grid;\n gap: var(--office-space-2);\n}\nselect {\n font: inherit;\n padding: var(--office-space-2);\n color: inherit;\n border: var(--office-border-width) solid var(--office-field-border);\n border-radius: var(--office-radius);\n background: var(--office-field-background);\n}\n.connection {\n color: var(--office-teams-text-subtle);\n margin-bottom: 0;\n font-size: var(--office-font-size-sm);\n}\n:focus-visible {\n outline: var(--office-focus-width) solid var(--office-ring);\n outline-offset: var(--office-focus-offset);\n}\n";
|
|
3566
|
+
var profile_menu_default = ":host {\n display: inline-flex;\n font: inherit;\n color: inherit;\n}\n.profile {\n display: inline-flex;\n align-items: center;\n padding: var(--office-space-1);\n border: 0;\n border-radius: var(--office-radius-full);\n background: transparent;\n cursor: pointer;\n}\n.profile:hover {\n background: var(--office-selected);\n}\n[popover] {\n min-width: 20em;\n max-width: 90vw;\n max-height: min(80vh, 40em);\n overflow: auto;\n padding: var(--office-space-4);\n border: var(--office-border-width) solid var(--office-teams-divider);\n border-radius: var(--office-radius-md);\n background: var(--office-popover);\n color: var(--office-foreground);\n box-shadow: var(--office-shadow-teams);\n}\n.identity {\n display: flex;\n gap: var(--office-space-3);\n align-items: center;\n margin-bottom: var(--office-space-4);\n}\n.identity strong {\n overflow-wrap: anywhere;\n}\nlabel {\n display: grid;\n gap: var(--office-space-2);\n margin-bottom: var(--office-space-3);\n}\n.who {\n display: grid;\n min-width: 0;\n}\n.status-line,\n.message,\n.hint {\n color: var(--office-teams-text-subtle);\n font-size: var(--office-font-size-sm);\n overflow-wrap: anywhere;\n}\n.hint:empty {\n display: none;\n}\n.actions {\n display: flex;\n flex-wrap: wrap;\n gap: var(--office-space-2);\n margin-bottom: var(--office-space-3);\n}\n.actions button {\n padding: var(--office-space-2) var(--office-space-3);\n border: var(--office-border-width) solid var(--office-teams-divider);\n border-radius: var(--office-radius-md);\n background: var(--office-background);\n color: inherit;\n font: inherit;\n cursor: pointer;\n}\n.actions button:hover:not(:disabled) {\n background: var(--office-selected);\n}\n.actions button:disabled {\n opacity: 0.5;\n cursor: default;\n}\n@media (pointer: coarse) {\n .actions button,\n select,\n input {\n min-height: var(--office-touch-target, 44px);\n }\n}\ninput,\nselect {\n font: inherit;\n padding: var(--office-space-2);\n color: inherit;\n border: var(--office-border-width) solid var(--office-field-border);\n border-radius: var(--office-radius);\n background: var(--office-field-background);\n}\nselect:disabled {\n opacity: 0.6;\n}\n.connection {\n color: var(--office-teams-text-subtle);\n margin-bottom: 0;\n font-size: var(--office-font-size-sm);\n}\n:focus-visible {\n outline: var(--office-focus-width) solid var(--office-ring);\n outline-offset: var(--office-focus-offset);\n}\n";
|
|
2626
3567
|
|
|
2627
3568
|
// src/teams/app/profile-menu.ts
|
|
2628
|
-
var
|
|
3569
|
+
var idleLabel = (minutes) => minutes === 0 ? "Never" : `${minutes} minutes`;
|
|
3570
|
+
var untilLabel = (at) => {
|
|
3571
|
+
if (at === null) return "";
|
|
3572
|
+
const d = new Date(at);
|
|
3573
|
+
const today = (/* @__PURE__ */ new Date()).toDateString();
|
|
3574
|
+
if (d.getHours() === 0 && d.getMinutes() === 0) {
|
|
3575
|
+
const lastDay = new Date(at - 1);
|
|
3576
|
+
return lastDay.toDateString() === today ? "Until end of today" : `Until end of ${lastDay.toLocaleDateString([], { weekday: "long" })}`;
|
|
3577
|
+
}
|
|
3578
|
+
const time = d.toLocaleTimeString([], { hour: "numeric", minute: "2-digit" });
|
|
3579
|
+
return d.toDateString() === today ? `Until ${time}` : `Until ${d.toLocaleDateString([], { weekday: "long" })} ${time}`;
|
|
3580
|
+
};
|
|
2629
3581
|
var TeamsProfileMenu = class extends LitElement {
|
|
2630
3582
|
static styles = unsafeCSS(profile_menu_default);
|
|
2631
|
-
static properties = {
|
|
3583
|
+
static properties = {
|
|
3584
|
+
state: { attribute: false },
|
|
3585
|
+
open: { state: true },
|
|
3586
|
+
draft: { state: true },
|
|
3587
|
+
resetAfter: { state: true },
|
|
3588
|
+
clearAfter: { state: true }
|
|
3589
|
+
};
|
|
2632
3590
|
constructor() {
|
|
2633
3591
|
super();
|
|
2634
3592
|
this.state = null;
|
|
2635
3593
|
this.open = false;
|
|
3594
|
+
this.draft = null;
|
|
3595
|
+
this.resetAfter = "never";
|
|
3596
|
+
this.clearAfter = "never";
|
|
2636
3597
|
}
|
|
2637
3598
|
willUpdate(changed) {
|
|
2638
3599
|
const old = changed.get("state");
|
|
@@ -2644,9 +3605,27 @@ var TeamsProfileMenu = class extends LitElement {
|
|
|
2644
3605
|
if (toggleAnchoredPopover(panel, this.renderRoot.querySelector("button")))
|
|
2645
3606
|
panel.querySelector("select")?.focus();
|
|
2646
3607
|
}
|
|
3608
|
+
fire(name, detail) {
|
|
3609
|
+
this.dispatchEvent(new CustomEvent(name, { detail, bubbles: true, composed: true }));
|
|
3610
|
+
}
|
|
3611
|
+
saveMessage() {
|
|
3612
|
+
this.fire("teams-profile-message", {
|
|
3613
|
+
message: this.draft ?? this.state?.presence.message ?? "",
|
|
3614
|
+
duration: this.clearAfter
|
|
3615
|
+
});
|
|
3616
|
+
this.draft = null;
|
|
3617
|
+
}
|
|
3618
|
+
durationOptions(selected) {
|
|
3619
|
+
return STATUS_DURATIONS.map(
|
|
3620
|
+
(value) => html`<option value=${value} ?selected=${selected === value}>
|
|
3621
|
+
${STATUS_DURATION_LABELS[value]}
|
|
3622
|
+
</option>`
|
|
3623
|
+
);
|
|
3624
|
+
}
|
|
2647
3625
|
render() {
|
|
2648
3626
|
const state = this.state;
|
|
2649
3627
|
if (!state) return nothing;
|
|
3628
|
+
const { presence } = state;
|
|
2650
3629
|
return html`<button
|
|
2651
3630
|
type="button"
|
|
2652
3631
|
class="profile"
|
|
@@ -2686,25 +3665,91 @@ var TeamsProfileMenu = class extends LitElement {
|
|
|
2686
3665
|
name=${state.user.name}
|
|
2687
3666
|
seed=${state.user.id}
|
|
2688
3667
|
presence=${state.availability}
|
|
2689
|
-
></office-ui-avatar
|
|
2690
|
-
|
|
3668
|
+
></office-ui-avatar>
|
|
3669
|
+
<div class="who">
|
|
3670
|
+
<strong>${state.user.name}</strong>
|
|
3671
|
+
<span class="status-line"
|
|
3672
|
+
>${PRESENCE_LABELS[state.availability]}${state.presence.idle && state.presence.status === "available" ? " (idle)" : ""}</span
|
|
3673
|
+
>
|
|
3674
|
+
${presence.message ? html`<span class="message">${presence.message}</span>` : nothing}
|
|
3675
|
+
</div>
|
|
2691
3676
|
</div>
|
|
2692
3677
|
<label
|
|
2693
3678
|
>Availability<select
|
|
2694
|
-
.value=${
|
|
3679
|
+
.value=${presence.status}
|
|
2695
3680
|
@change=${(event) => {
|
|
2696
3681
|
const availability = event.target.value;
|
|
2697
|
-
if (
|
|
2698
|
-
|
|
2699
|
-
new CustomEvent("teams-profile-status", {
|
|
2700
|
-
detail: { availability },
|
|
2701
|
-
bubbles: true,
|
|
2702
|
-
composed: true
|
|
2703
|
-
})
|
|
2704
|
-
);
|
|
3682
|
+
if (!isPresenceStatus(availability)) return;
|
|
3683
|
+
this.fire("teams-profile-status", { availability, duration: this.resetAfter });
|
|
2705
3684
|
}}
|
|
2706
3685
|
>
|
|
2707
|
-
${
|
|
3686
|
+
${PRESENCE_STATUSES.map((value) => html`<option value=${value} ?selected=${presence.status === value}>${PRESENCE_LABELS[value]}</option>`)}
|
|
3687
|
+
</select></label
|
|
3688
|
+
>
|
|
3689
|
+
<label
|
|
3690
|
+
>Reset status after<select
|
|
3691
|
+
name="status-duration"
|
|
3692
|
+
@change=${(event) => {
|
|
3693
|
+
const duration = event.target.value;
|
|
3694
|
+
if (!isStatusDuration(duration)) return;
|
|
3695
|
+
this.resetAfter = duration;
|
|
3696
|
+
this.fire("teams-profile-status", { availability: presence.status, duration });
|
|
3697
|
+
}}
|
|
3698
|
+
>
|
|
3699
|
+
${this.durationOptions(this.resetAfter)}
|
|
3700
|
+
</select>
|
|
3701
|
+
<span class="hint">${untilLabel(presence.statusExpiresAt)}</span></label
|
|
3702
|
+
>
|
|
3703
|
+
<label
|
|
3704
|
+
>Status message<input
|
|
3705
|
+
type="text"
|
|
3706
|
+
name="message"
|
|
3707
|
+
maxlength=${MAX_STATUS_MESSAGE_CHARS}
|
|
3708
|
+
placeholder="What's your status message?"
|
|
3709
|
+
.value=${this.draft ?? presence.message}
|
|
3710
|
+
@input=${(event) => this.draft = event.target.value}
|
|
3711
|
+
@keydown=${(event) => {
|
|
3712
|
+
if (event.key !== "Enter") return;
|
|
3713
|
+
event.preventDefault();
|
|
3714
|
+
this.saveMessage();
|
|
3715
|
+
}}
|
|
3716
|
+
/>
|
|
3717
|
+
<span class="hint">${untilLabel(presence.messageExpiresAt)}</span></label
|
|
3718
|
+
>
|
|
3719
|
+
<label
|
|
3720
|
+
>Clear status message after<select
|
|
3721
|
+
name="message-duration"
|
|
3722
|
+
@change=${(event) => {
|
|
3723
|
+
const duration = event.target.value;
|
|
3724
|
+
if (isStatusDuration(duration)) this.clearAfter = duration;
|
|
3725
|
+
}}
|
|
3726
|
+
>
|
|
3727
|
+
${this.durationOptions(this.clearAfter)}
|
|
3728
|
+
</select></label
|
|
3729
|
+
>
|
|
3730
|
+
<div class="actions">
|
|
3731
|
+
<button type="button" @click=${this.saveMessage}>Save message</button>
|
|
3732
|
+
<button
|
|
3733
|
+
type="button"
|
|
3734
|
+
?disabled=${!presence.message && !this.draft}
|
|
3735
|
+
@click=${() => {
|
|
3736
|
+
this.draft = "";
|
|
3737
|
+
this.saveMessage();
|
|
3738
|
+
}}
|
|
3739
|
+
>
|
|
3740
|
+
Clear message
|
|
3741
|
+
</button>
|
|
3742
|
+
</div>
|
|
3743
|
+
<label
|
|
3744
|
+
>Show me as away after<select
|
|
3745
|
+
name="idle"
|
|
3746
|
+
@change=${(event) => {
|
|
3747
|
+
const minutes = Number(event.target.value);
|
|
3748
|
+
if (IDLE_MINUTE_CHOICES.includes(minutes))
|
|
3749
|
+
this.fire("teams-profile-idle", { minutes });
|
|
3750
|
+
}}
|
|
3751
|
+
>
|
|
3752
|
+
${IDLE_MINUTE_CHOICES.map((minutes) => html`<option value=${minutes} ?selected=${presence.idleMinutes === minutes}>${idleLabel(minutes)}</option>`)}
|
|
2708
3753
|
</select></label
|
|
2709
3754
|
>
|
|
2710
3755
|
<p class="connection">
|
|
@@ -2718,6 +3763,157 @@ function defineTeamsProfileMenu() {
|
|
|
2718
3763
|
customElements.define("teams-profile-menu", TeamsProfileMenu);
|
|
2719
3764
|
}
|
|
2720
3765
|
|
|
3766
|
+
// raw-css:/home/runner/work/ooxml/ooxml/src/ui/src/teams/app/pinned-bar.css?raw
|
|
3767
|
+
var pinned_bar_default = ":host {\n display: block;\n flex: none;\n font: inherit;\n color: inherit;\n}\n*,\n*::before,\n*::after {\n box-sizing: border-box;\n}\nsection {\n background: var(--office-teams-panel);\n border-block-end: var(--office-border-width) solid var(--office-teams-divider);\n}\nbutton {\n font: inherit;\n color: inherit;\n cursor: pointer;\n border: 0;\n background: transparent;\n}\n.summary {\n display: flex;\n align-items: center;\n gap: var(--office-space-2);\n padding: var(--office-space-1) var(--office-space-3);\n}\n.latest {\n display: flex;\n flex: 1;\n align-items: center;\n gap: var(--office-space-2);\n min-width: 0;\n min-height: 2.2em;\n padding: var(--office-space-1) var(--office-space-2);\n border-radius: var(--office-radius);\n text-align: start;\n}\n.latest:hover,\n.count:hover,\n.jump:hover,\n.unpin:hover {\n background: var(--office-selected);\n}\n.mark {\n display: inline-grid;\n flex: none;\n color: var(--office-teams-brand);\n}\nsvg {\n width: 1.1em;\n height: 1.1em;\n fill: none;\n stroke: currentColor;\n stroke-width: var(--office-icon-stroke);\n stroke-linecap: round;\n stroke-linejoin: round;\n}\n.text {\n min-width: 0;\n overflow: hidden;\n color: var(--office-teams-text-subtle);\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.count {\n flex: none;\n min-height: 2.2em;\n padding: var(--office-space-1) var(--office-space-3);\n border-radius: var(--office-radius);\n color: var(--office-teams-brand);\n font-weight: var(--office-font-weight-bold);\n}\nul {\n display: grid;\n gap: var(--office-space-1);\n max-height: 14em;\n margin: 0;\n padding: 0 var(--office-space-3) var(--office-space-2);\n overflow: auto;\n list-style: none;\n}\nli {\n display: flex;\n align-items: center;\n gap: var(--office-space-2);\n border: var(--office-border-width) solid var(--office-teams-divider);\n border-radius: var(--office-radius-md);\n background: var(--office-background);\n}\n.jump {\n display: grid;\n flex: 1;\n gap: var(--office-space-0);\n min-width: 0;\n padding: var(--office-space-2) var(--office-space-3);\n border-radius: var(--office-radius-md);\n text-align: start;\n}\n.by {\n color: var(--office-teams-text-subtle);\n font-size: var(--office-font-size-xs);\n}\n.unpin {\n flex: none;\n margin-inline-end: var(--office-space-2);\n padding: var(--office-space-1) var(--office-space-3);\n border-radius: var(--office-radius);\n}\n:focus-visible {\n outline: var(--office-focus-width) solid var(--office-ring);\n outline-offset: var(--office-focus-offset);\n}\n@media (pointer: coarse) {\n .latest,\n .count,\n .unpin {\n min-height: var(--office-touch-target, 44px);\n }\n .unpin {\n min-width: var(--office-touch-target, 44px);\n }\n}\n";
|
|
3768
|
+
|
|
3769
|
+
// src/teams/app/pinned-bar.ts
|
|
3770
|
+
var SNIPPET = 140;
|
|
3771
|
+
var snippet = (m) => {
|
|
3772
|
+
const text = m.text.replace(/\s+/gu, " ").trim();
|
|
3773
|
+
if (text) return text.length > SNIPPET ? `${text.slice(0, SNIPPET)}...` : text;
|
|
3774
|
+
return m.attachments[0]?.name ?? "Attachment";
|
|
3775
|
+
};
|
|
3776
|
+
var TeamsPinnedBar = class extends LitElement {
|
|
3777
|
+
static styles = unsafeCSS(pinned_bar_default);
|
|
3778
|
+
static properties = { pinned: { attribute: false }, expanded: { state: true } };
|
|
3779
|
+
constructor() {
|
|
3780
|
+
super();
|
|
3781
|
+
this.pinned = [];
|
|
3782
|
+
this.expanded = false;
|
|
3783
|
+
}
|
|
3784
|
+
emit(name, messageId) {
|
|
3785
|
+
this.dispatchEvent(
|
|
3786
|
+
new CustomEvent(name, { detail: { messageId }, bubbles: true, composed: true })
|
|
3787
|
+
);
|
|
3788
|
+
}
|
|
3789
|
+
render() {
|
|
3790
|
+
const [latest] = this.pinned;
|
|
3791
|
+
if (!latest) return nothing;
|
|
3792
|
+
return html`
|
|
3793
|
+
<section aria-label="Pinned messages">
|
|
3794
|
+
<div class="summary">
|
|
3795
|
+
<button
|
|
3796
|
+
type="button"
|
|
3797
|
+
class="latest"
|
|
3798
|
+
@click=${() => this.emit("teams-pinned-open", latest.message.id)}
|
|
3799
|
+
>
|
|
3800
|
+
<span class="mark">${icon("pin")}</span>
|
|
3801
|
+
<strong>${latest.message.authorName}</strong>
|
|
3802
|
+
<span class="text">${snippet(latest.message)}</span>
|
|
3803
|
+
</button>
|
|
3804
|
+
<button
|
|
3805
|
+
type="button"
|
|
3806
|
+
class="count"
|
|
3807
|
+
aria-expanded=${String(this.expanded)}
|
|
3808
|
+
aria-controls="pins"
|
|
3809
|
+
@click=${() => this.expanded = !this.expanded}
|
|
3810
|
+
>
|
|
3811
|
+
${this.pinned.length} pinned
|
|
3812
|
+
</button>
|
|
3813
|
+
</div>
|
|
3814
|
+
${this.expanded ? html`<ul id="pins">
|
|
3815
|
+
${this.pinned.map(
|
|
3816
|
+
(pin) => html`<li>
|
|
3817
|
+
<button
|
|
3818
|
+
type="button"
|
|
3819
|
+
class="jump"
|
|
3820
|
+
@click=${() => this.emit("teams-pinned-open", pin.message.id)}
|
|
3821
|
+
>
|
|
3822
|
+
<strong>${pin.message.authorName}</strong>
|
|
3823
|
+
<span class="text">${snippet(pin.message)}</span>
|
|
3824
|
+
<span class="by">Pinned by ${pin.pinnedByName}</span>
|
|
3825
|
+
</button>
|
|
3826
|
+
<button
|
|
3827
|
+
type="button"
|
|
3828
|
+
class="unpin"
|
|
3829
|
+
aria-label=${`Unpin message from ${pin.message.authorName}`}
|
|
3830
|
+
title="Unpin"
|
|
3831
|
+
@click=${() => this.emit("teams-pinned-unpin", pin.message.id)}
|
|
3832
|
+
>
|
|
3833
|
+
Unpin
|
|
3834
|
+
</button>
|
|
3835
|
+
</li>`
|
|
3836
|
+
)}
|
|
3837
|
+
</ul>` : nothing}
|
|
3838
|
+
</section>
|
|
3839
|
+
`;
|
|
3840
|
+
}
|
|
3841
|
+
};
|
|
3842
|
+
function defineTeamsPinnedBar() {
|
|
3843
|
+
if (!customElements.get("teams-pinned-bar"))
|
|
3844
|
+
customElements.define("teams-pinned-bar", TeamsPinnedBar);
|
|
3845
|
+
}
|
|
3846
|
+
|
|
3847
|
+
// src/teams/app/activity.ts
|
|
3848
|
+
var ACTIVITY_EVENTS = ["pointerdown", "pointermove", "keydown", "wheel", "touchstart"];
|
|
3849
|
+
function watchActivity(target, onActivity, throttleMs = 1e3, now = Date.now) {
|
|
3850
|
+
let last = Number.NEGATIVE_INFINITY;
|
|
3851
|
+
const handler = () => {
|
|
3852
|
+
const t = now();
|
|
3853
|
+
if (t - last < throttleMs) return;
|
|
3854
|
+
last = t;
|
|
3855
|
+
onActivity();
|
|
3856
|
+
};
|
|
3857
|
+
for (const name of ACTIVITY_EVENTS) target.addEventListener(name, handler, { passive: true });
|
|
3858
|
+
return () => {
|
|
3859
|
+
for (const name of ACTIVITY_EVENTS) target.removeEventListener(name, handler);
|
|
3860
|
+
};
|
|
3861
|
+
}
|
|
3862
|
+
function deliverNotification(item, settings, env, actions) {
|
|
3863
|
+
let result = "none";
|
|
3864
|
+
if (!env.hidden()) {
|
|
3865
|
+
actions.toast(item);
|
|
3866
|
+
result = "toast";
|
|
3867
|
+
} else if (env.permission() === "granted") {
|
|
3868
|
+
env.show(
|
|
3869
|
+
describeActivity(item),
|
|
3870
|
+
{ body: item.preview, tag: item.id },
|
|
3871
|
+
() => actions.open(item)
|
|
3872
|
+
);
|
|
3873
|
+
result = "desktop";
|
|
3874
|
+
}
|
|
3875
|
+
if (result !== "none" && settings.sound) env.beep();
|
|
3876
|
+
return result;
|
|
3877
|
+
}
|
|
3878
|
+
function chime() {
|
|
3879
|
+
try {
|
|
3880
|
+
const Context = globalThis.AudioContext ?? globalThis.webkitAudioContext;
|
|
3881
|
+
if (!Context) return;
|
|
3882
|
+
const audio = new Context();
|
|
3883
|
+
const gain = audio.createGain();
|
|
3884
|
+
gain.gain.setValueAtTime(0.06, audio.currentTime);
|
|
3885
|
+
gain.gain.exponentialRampToValueAtTime(1e-4, audio.currentTime + 0.35);
|
|
3886
|
+
gain.connect(audio.destination);
|
|
3887
|
+
[660, 880].forEach((frequency, index) => {
|
|
3888
|
+
const tone = audio.createOscillator();
|
|
3889
|
+
tone.frequency.value = frequency;
|
|
3890
|
+
tone.connect(gain);
|
|
3891
|
+
tone.start(audio.currentTime + index * 0.12);
|
|
3892
|
+
tone.stop(audio.currentTime + index * 0.12 + 0.12);
|
|
3893
|
+
});
|
|
3894
|
+
globalThis.setTimeout(() => void audio.close(), 700);
|
|
3895
|
+
} catch {
|
|
3896
|
+
}
|
|
3897
|
+
}
|
|
3898
|
+
function browserDeliveryEnv() {
|
|
3899
|
+
return {
|
|
3900
|
+
hidden: () => globalThis.document?.visibilityState === "hidden",
|
|
3901
|
+
permission: () => globalThis.Notification?.permission ?? "unsupported",
|
|
3902
|
+
show(title, options, onClick) {
|
|
3903
|
+
try {
|
|
3904
|
+
const notification = new globalThis.Notification(title, options);
|
|
3905
|
+
notification.onclick = () => {
|
|
3906
|
+
globalThis.focus();
|
|
3907
|
+
notification.close();
|
|
3908
|
+
onClick();
|
|
3909
|
+
};
|
|
3910
|
+
} catch {
|
|
3911
|
+
}
|
|
3912
|
+
},
|
|
3913
|
+
beep: chime
|
|
3914
|
+
};
|
|
3915
|
+
}
|
|
3916
|
+
|
|
2721
3917
|
// raw-css:/home/runner/work/ooxml/ooxml/src/ui/src/teams/app/add-tab-dialog.css?raw
|
|
2722
3918
|
var add_tab_dialog_default = ":host {\n font: var(--office-font-size) var(--office-font);\n color: var(--office-foreground);\n}\ndialog {\n box-sizing: border-box;\n width: min(54em, 94vw);\n max-height: 90vh;\n padding: 0;\n border: var(--office-border-width) solid var(--office-teams-divider);\n border-radius: var(--office-radius-lg);\n color: inherit;\n background: var(--office-popover);\n box-shadow: var(--office-shadow-teams);\n}\ndialog::backdrop {\n background: var(--office-overlay);\n}\nheader,\n.app-heading,\nfooter {\n display: flex;\n align-items: center;\n gap: var(--office-space-3);\n}\nheader {\n justify-content: space-between;\n padding: var(--office-space-4) var(--office-space-5);\n border-bottom: var(--office-border-width) solid var(--office-teams-divider);\n}\nh1,\nh2 {\n margin: 0;\n font-size: var(--office-font-size-lg);\n}\nsection,\nform {\n padding: var(--office-space-5);\n}\nform {\n display: grid;\n gap: var(--office-space-3);\n}\n.apps {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(10em, 1fr));\n gap: var(--office-space-3);\n}\nbutton,\ninput {\n font: inherit;\n color: inherit;\n border: var(--office-border-width) solid var(--office-field-border);\n border-radius: var(--office-radius);\n background: var(--office-field-background);\n padding: var(--office-space-2) var(--office-space-3);\n}\nbutton {\n cursor: pointer;\n}\nbutton:hover:not(:disabled) {\n background: var(--office-selected);\n}\nbutton:disabled {\n opacity: 0.5;\n cursor: default;\n}\n.app {\n display: grid;\n justify-items: start;\n text-align: start;\n gap: var(--office-space-2);\n padding: var(--office-space-4);\n}\n.app-heading h2 {\n flex: 1;\n}\n.badge {\n display: grid;\n place-items: center;\n width: 2.6em;\n height: 2.6em;\n border-radius: var(--office-radius-md);\n color: var(--office-call-foreground);\n background: var(--office-file-other);\n font-weight: var(--office-font-weight-bold);\n}\n.badge[data-kind='docx'] {\n background: var(--office-file-docx);\n}\n.badge[data-kind='xlsx'] {\n background: var(--office-file-xlsx);\n}\n.badge[data-kind='pptx'] {\n background: var(--office-file-pptx);\n}\n.badge[data-kind='vsdx'] {\n background: var(--office-file-vsdx);\n}\nlabel {\n display: grid;\n gap: var(--office-space-2);\n}\ninput {\n min-width: 0;\n}\nsmall,\n.hint,\nsection > p {\n color: var(--office-teams-text-subtle);\n line-height: 1.5;\n}\nsmall {\n display: block;\n}\n.files {\n margin: 0;\n padding: var(--office-space-2);\n max-height: 18em;\n overflow: auto;\n border: var(--office-border-width) solid var(--office-teams-divider);\n border-radius: var(--office-radius);\n}\n.file {\n display: flex;\n align-items: center;\n gap: var(--office-space-3);\n padding: var(--office-space-3);\n border-radius: var(--office-radius);\n cursor: pointer;\n}\n.file:has(input:checked) {\n background: var(--office-teams-brand-subtle);\n}\n.file strong {\n overflow-wrap: anywhere;\n}\n[role='alert'] {\n color: var(--office-danger);\n}\nfooter {\n justify-content: flex-end;\n}\n.post-choice {\n display: flex;\n align-items: center;\n gap: var(--office-space-2);\n}\nbutton.primary {\n color: var(--office-teams-brand-foreground);\n border-color: var(--office-teams-brand);\n background: var(--office-teams-brand);\n}\nbutton.primary:hover:not(:disabled) {\n background: var(--office-teams-brand-hover);\n}\n:focus-visible {\n outline: var(--office-focus-width) solid var(--office-ring);\n outline-offset: var(--office-focus-offset);\n}\n";
|
|
2723
3919
|
|
|
@@ -2964,129 +4160,6 @@ function defineTeamsAddTabDialog() {
|
|
|
2964
4160
|
customElements.define("teams-add-tab-dialog", TeamsAddTabDialog);
|
|
2965
4161
|
}
|
|
2966
4162
|
|
|
2967
|
-
// raw-css:/home/runner/work/ooxml/ooxml/src/ui/src/teams/app/navigation-drawer.css?raw
|
|
2968
|
-
var navigation_drawer_default = ":host {\n font: var(--office-font-size) var(--office-font);\n color: var(--office-foreground);\n}\ndialog {\n box-sizing: border-box;\n inset: 0 auto 0 0;\n margin: 0;\n width: min(24em, 92vw);\n max-width: 92vw;\n height: 100dvh;\n max-height: 100dvh;\n padding: 0;\n border: 0;\n border-inline-end: var(--office-border-width) solid var(--office-teams-divider);\n background: var(--office-teams-panel);\n color: inherit;\n box-shadow: var(--office-shadow-teams);\n}\ndialog[open] {\n display: flex;\n flex-direction: column;\n}\ndialog::backdrop {\n background: var(--office-overlay);\n}\nheader {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--office-space-3);\n padding: var(--office-space-3) var(--office-space-4);\n border-block-end: var(--office-border-width) solid var(--office-teams-divider);\n}\nh2 {\n margin: 0;\n font-size: var(--office-font-size-lg);\n}\nbutton {\n padding: var(--office-space-2) var(--office-space-3);\n border: var(--office-border-width) solid var(--office-teams-divider);\n border-radius: var(--office-radius-md);\n font: inherit;\n background: var(--office-background);\n color: inherit;\n cursor: pointer;\n}\nbutton:hover {\n background: var(--office-selected);\n}\nbutton:focus-visible {\n outline: var(--office-focus-width) solid var(--office-ring);\n outline-offset: var(--office-focus-offset);\n}\nnav {\n flex: 1;\n min-height: 0;\n overflow: auto;\n overscroll-behavior: contain;\n}\n";
|
|
2969
|
-
|
|
2970
|
-
// src/dialog/focus.ts
|
|
2971
|
-
var MODAL_FOCUSABLE_SELECTOR = [
|
|
2972
|
-
"a[href]",
|
|
2973
|
-
"button:not([disabled])",
|
|
2974
|
-
'input:not([disabled]):not([type="hidden"])',
|
|
2975
|
-
"select:not([disabled])",
|
|
2976
|
-
"textarea:not([disabled])",
|
|
2977
|
-
'[contenteditable="true"]',
|
|
2978
|
-
'[tabindex]:not([tabindex="-1"])'
|
|
2979
|
-
].join(",");
|
|
2980
|
-
function isAvailable(element) {
|
|
2981
|
-
if (element.hidden || element.getAttribute("aria-hidden") === "true") {
|
|
2982
|
-
return false;
|
|
2983
|
-
}
|
|
2984
|
-
const style = element.ownerDocument.defaultView?.getComputedStyle(element);
|
|
2985
|
-
return style?.display !== "none" && style?.visibility !== "hidden";
|
|
2986
|
-
}
|
|
2987
|
-
function focusableElements(root, found = []) {
|
|
2988
|
-
for (const child of Array.from(root.children)) {
|
|
2989
|
-
if (child instanceof HTMLElement) {
|
|
2990
|
-
if (!isAvailable(child)) continue;
|
|
2991
|
-
if (child.matches(MODAL_FOCUSABLE_SELECTOR) && isAvailable(child)) {
|
|
2992
|
-
found.push(child);
|
|
2993
|
-
}
|
|
2994
|
-
if (child.shadowRoot && isAvailable(child)) {
|
|
2995
|
-
focusableElements(child.shadowRoot, found);
|
|
2996
|
-
}
|
|
2997
|
-
}
|
|
2998
|
-
focusableElements(child, found);
|
|
2999
|
-
}
|
|
3000
|
-
return found;
|
|
3001
|
-
}
|
|
3002
|
-
function deepActiveElement(doc) {
|
|
3003
|
-
let active = doc.activeElement;
|
|
3004
|
-
while (active?.shadowRoot?.activeElement) {
|
|
3005
|
-
active = active.shadowRoot.activeElement;
|
|
3006
|
-
}
|
|
3007
|
-
return active;
|
|
3008
|
-
}
|
|
3009
|
-
function modalFocusableElements(panel) {
|
|
3010
|
-
return focusableElements(panel);
|
|
3011
|
-
}
|
|
3012
|
-
function modalActiveElement(doc) {
|
|
3013
|
-
return deepActiveElement(doc);
|
|
3014
|
-
}
|
|
3015
|
-
|
|
3016
|
-
// src/teams/app/navigation-drawer.ts
|
|
3017
|
-
var TeamsNavigationDrawer = class extends LitElement {
|
|
3018
|
-
static styles = unsafeCSS(navigation_drawer_default);
|
|
3019
|
-
static properties = {
|
|
3020
|
-
open: { type: Boolean, reflect: true },
|
|
3021
|
-
heading: { type: String }
|
|
3022
|
-
};
|
|
3023
|
-
compact;
|
|
3024
|
-
resized = () => {
|
|
3025
|
-
if (this.open && !this.compact?.matches) this.close();
|
|
3026
|
-
};
|
|
3027
|
-
constructor() {
|
|
3028
|
-
super();
|
|
3029
|
-
this.open = false;
|
|
3030
|
-
this.heading = "Teams and channels";
|
|
3031
|
-
this.addEventListener("keydown", (event) => this.trapTab(event));
|
|
3032
|
-
}
|
|
3033
|
-
connectedCallback() {
|
|
3034
|
-
super.connectedCallback();
|
|
3035
|
-
this.compact = globalThis.matchMedia?.("(max-width: 56.25em)");
|
|
3036
|
-
this.compact?.addEventListener("change", this.resized);
|
|
3037
|
-
}
|
|
3038
|
-
disconnectedCallback() {
|
|
3039
|
-
this.compact?.removeEventListener("change", this.resized);
|
|
3040
|
-
super.disconnectedCallback();
|
|
3041
|
-
}
|
|
3042
|
-
updated() {
|
|
3043
|
-
const dialog = this.renderRoot.querySelector("dialog");
|
|
3044
|
-
if (this.open && !dialog.open) dialog.showModal();
|
|
3045
|
-
else if (!this.open && dialog.open) dialog.close();
|
|
3046
|
-
}
|
|
3047
|
-
trapTab(event) {
|
|
3048
|
-
if (!this.open || event.key !== "Tab") return;
|
|
3049
|
-
const close = this.renderRoot.querySelector("button");
|
|
3050
|
-
const stops = [close, ...modalFocusableElements(this)];
|
|
3051
|
-
const current = modalActiveElement(this.ownerDocument);
|
|
3052
|
-
const index = stops.findIndex((element) => element === current);
|
|
3053
|
-
if (index < 0 || (event.shiftKey ? index === 0 : index === stops.length - 1)) {
|
|
3054
|
-
event.preventDefault();
|
|
3055
|
-
stops[event.shiftKey ? stops.length - 1 : 0]?.focus();
|
|
3056
|
-
}
|
|
3057
|
-
}
|
|
3058
|
-
close() {
|
|
3059
|
-
this.dispatchEvent(
|
|
3060
|
-
new CustomEvent("teams-navigation-close", { bubbles: true, composed: true })
|
|
3061
|
-
);
|
|
3062
|
-
}
|
|
3063
|
-
render() {
|
|
3064
|
-
return html`<dialog
|
|
3065
|
-
aria-label="Workspace navigation"
|
|
3066
|
-
@click=${(event) => {
|
|
3067
|
-
const dialog = event.currentTarget;
|
|
3068
|
-
const rect = dialog.getBoundingClientRect();
|
|
3069
|
-
if (event.target === dialog && (event.clientX < rect.left || event.clientX > rect.right || event.clientY < rect.top || event.clientY > rect.bottom))
|
|
3070
|
-
this.close();
|
|
3071
|
-
}}
|
|
3072
|
-
@cancel=${(event) => {
|
|
3073
|
-
event.preventDefault();
|
|
3074
|
-
this.close();
|
|
3075
|
-
}}
|
|
3076
|
-
>
|
|
3077
|
-
<header>
|
|
3078
|
-
<h2>${this.heading}</h2>
|
|
3079
|
-
<button type="button" aria-label="Close navigation" @click=${this.close}>×</button>
|
|
3080
|
-
</header>
|
|
3081
|
-
<nav aria-label="Workspace channels and calls"><slot></slot></nav>
|
|
3082
|
-
</dialog>`;
|
|
3083
|
-
}
|
|
3084
|
-
};
|
|
3085
|
-
function defineTeamsNavigationDrawer(registry = globalThis.customElements) {
|
|
3086
|
-
if (registry && !registry.get("teams-navigation-drawer"))
|
|
3087
|
-
registry.define("teams-navigation-drawer", TeamsNavigationDrawer);
|
|
3088
|
-
}
|
|
3089
|
-
|
|
3090
4163
|
// raw-css:/home/runner/work/ooxml/ooxml/src/ui/src/teams/app/create-channel-dialog.css?raw
|
|
3091
4164
|
var create_channel_dialog_default = ":host {\n font: var(--office-font-size) var(--office-font);\n color: var(--office-foreground);\n}\ndialog {\n box-sizing: border-box;\n width: min(40em, 94vw);\n max-height: 90dvh;\n padding: 0;\n border: var(--office-border-width) solid var(--office-teams-divider);\n border-radius: var(--office-radius-lg);\n background: var(--office-popover);\n color: inherit;\n box-shadow: var(--office-shadow-teams);\n}\ndialog::backdrop {\n background: var(--office-overlay);\n}\nheader {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--office-space-3);\n padding: var(--office-space-4) var(--office-space-5);\n border-block-end: var(--office-border-width) solid var(--office-teams-divider);\n}\nh2 {\n margin: 0;\n font-size: var(--office-font-size-lg);\n}\nform {\n display: grid;\n gap: var(--office-space-3);\n padding: var(--office-space-5);\n}\nlabel {\n display: grid;\n gap: var(--office-space-2);\n font-weight: var(--office-font-weight-bold);\n}\ninput,\ntextarea {\n min-width: 0;\n width: 100%;\n box-sizing: border-box;\n padding: var(--office-space-3);\n font: inherit;\n font-weight: normal;\n color: inherit;\n background: var(--office-field-background);\n border: var(--office-border-width) solid var(--office-field-border);\n border-radius: var(--office-radius-md);\n}\ntextarea {\n min-height: 6em;\n resize: vertical;\n}\np,\nsmall {\n margin: 0;\n color: var(--office-teams-text-subtle);\n line-height: 1.5;\n}\n.issue {\n color: var(--office-danger);\n}\nfooter {\n display: flex;\n justify-content: flex-end;\n gap: var(--office-space-2);\n}\nbutton {\n padding: var(--office-space-2) var(--office-space-4);\n border: var(--office-border-width) solid var(--office-teams-divider);\n border-radius: var(--office-radius-md);\n background: var(--office-background);\n color: inherit;\n font: inherit;\n cursor: pointer;\n}\nbutton:hover {\n background: var(--office-selected);\n}\nbutton.primary {\n background: var(--office-teams-brand);\n color: var(--office-teams-brand-foreground);\n border-color: transparent;\n}\nbutton.primary:hover {\n background: var(--office-teams-brand-hover);\n}\n:focus-visible {\n outline: var(--office-focus-width) solid var(--office-ring);\n outline-offset: var(--office-focus-offset);\n}\n";
|
|
3092
4165
|
|
|
@@ -3191,17 +4264,724 @@ function defineTeamsCreateChannelDialog(registry = globalThis.customElements) {
|
|
|
3191
4264
|
registry.define("teams-create-channel-dialog", TeamsCreateChannelDialog);
|
|
3192
4265
|
}
|
|
3193
4266
|
|
|
4267
|
+
// raw-css:/home/runner/work/ooxml/ooxml/src/ui/src/teams/app/form-dialog.css?raw
|
|
4268
|
+
var form_dialog_default = "/* The frame shared by the Chat and Calendar dialogs: a modal <dialog> with a header, a form and a\n footer, in the same look as the create-channel dialog. */\n:host {\n font: var(--office-font-size) var(--office-font);\n color: var(--office-foreground);\n}\ndialog {\n box-sizing: border-box;\n width: min(40em, 94vw);\n max-height: 90dvh;\n padding: 0;\n overflow: auto;\n border: var(--office-border-width) solid var(--office-teams-divider);\n border-radius: var(--office-radius-lg);\n background: var(--office-popover);\n color: inherit;\n box-shadow: var(--office-shadow-teams);\n}\ndialog::backdrop {\n background: var(--office-overlay);\n}\ndialog > header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--office-space-3);\n padding: var(--office-space-4) var(--office-space-5);\n border-block-end: var(--office-border-width) solid var(--office-teams-divider);\n}\nh2 {\n margin: 0;\n font-size: var(--office-font-size-lg);\n}\nform,\n.body {\n display: grid;\n gap: var(--office-space-3);\n padding: var(--office-space-5);\n}\nlabel,\n.field {\n display: grid;\n gap: var(--office-space-2);\n font-weight: var(--office-font-weight-bold);\n}\ninput:not([type='checkbox']),\ntextarea,\nselect {\n min-width: 0;\n width: 100%;\n box-sizing: border-box;\n padding: var(--office-space-3);\n font: inherit;\n font-weight: normal;\n color: inherit;\n background: var(--office-field-background);\n border: var(--office-border-width) solid var(--office-field-border);\n border-radius: var(--office-radius-md);\n}\ntextarea {\n min-height: 6em;\n resize: vertical;\n}\np,\nsmall {\n margin: 0;\n color: var(--office-teams-text-subtle);\n line-height: 1.5;\n}\n.issue {\n color: var(--office-danger);\n}\nfooter {\n display: flex;\n flex-wrap: wrap;\n justify-content: flex-end;\n gap: var(--office-space-2);\n}\nbutton {\n padding: var(--office-space-2) var(--office-space-4);\n border: var(--office-border-width) solid var(--office-teams-divider);\n border-radius: var(--office-radius-md);\n background: var(--office-background);\n color: inherit;\n font: inherit;\n cursor: pointer;\n}\nbutton:hover {\n background: var(--office-selected);\n}\nbutton.primary {\n background: var(--office-teams-brand);\n color: var(--office-teams-brand-foreground);\n border-color: transparent;\n}\nbutton.primary:hover {\n background: var(--office-teams-brand-hover);\n}\nbutton.danger {\n color: var(--office-danger);\n}\nbutton:disabled {\n opacity: 0.5;\n cursor: default;\n}\n:focus-visible {\n outline: var(--office-focus-width) solid var(--office-ring);\n outline-offset: var(--office-focus-offset);\n}\n@media (max-width: 40em) {\n /* Full screen on a phone: the dialog is a page, not a floating card. */\n dialog {\n width: 100vw;\n max-width: 100vw;\n height: 100dvh;\n max-height: 100dvh;\n border-radius: 0;\n }\n button,\n input:not([type='checkbox']),\n select {\n min-height: 2.75em;\n }\n}\n";
|
|
4269
|
+
|
|
4270
|
+
// src/teams/app/dialog-base.ts
|
|
4271
|
+
var dialogStyles = (own = "") => withStyles(`${form_dialog_default}
|
|
4272
|
+
${own}`);
|
|
4273
|
+
var TeamsDialog = class extends TeamsElement {
|
|
4274
|
+
static properties = {
|
|
4275
|
+
open: { type: Boolean, reflect: true }
|
|
4276
|
+
};
|
|
4277
|
+
constructor() {
|
|
4278
|
+
super();
|
|
4279
|
+
this.open = false;
|
|
4280
|
+
}
|
|
4281
|
+
updated() {
|
|
4282
|
+
const dialog = this.renderRoot.querySelector("dialog");
|
|
4283
|
+
if (!dialog) return;
|
|
4284
|
+
if (this.open && !dialog.open) dialog.showModal();
|
|
4285
|
+
else if (!this.open && dialog.open) dialog.close();
|
|
4286
|
+
}
|
|
4287
|
+
requestClose() {
|
|
4288
|
+
this.fire("teams-dialog-close", {});
|
|
4289
|
+
}
|
|
4290
|
+
/** The dialog frame with a title and a close button around `body`. */
|
|
4291
|
+
frame(title, body, closeLabel = `Close ${title.toLowerCase()}`) {
|
|
4292
|
+
return html`<dialog
|
|
4293
|
+
aria-labelledby="title"
|
|
4294
|
+
@cancel=${(event) => {
|
|
4295
|
+
event.preventDefault();
|
|
4296
|
+
this.requestClose();
|
|
4297
|
+
}}
|
|
4298
|
+
>
|
|
4299
|
+
<header>
|
|
4300
|
+
<h2 id="title">${title}</h2>
|
|
4301
|
+
<button type="button" aria-label=${closeLabel} @click=${this.requestClose}>×</button>
|
|
4302
|
+
</header>
|
|
4303
|
+
${body}
|
|
4304
|
+
</dialog>`;
|
|
4305
|
+
}
|
|
4306
|
+
};
|
|
4307
|
+
|
|
4308
|
+
// raw-css:/home/runner/work/ooxml/ooxml/src/ui/src/teams/app/new-chat-dialog.css?raw
|
|
4309
|
+
var new_chat_dialog_default = "office-ui-people-picker {\n font-weight: normal;\n}\n";
|
|
4310
|
+
|
|
4311
|
+
// src/teams/app/new-chat-dialog.ts
|
|
4312
|
+
var TeamsNewChatDialog = class extends TeamsDialog {
|
|
4313
|
+
static styles = dialogStyles(new_chat_dialog_default);
|
|
4314
|
+
static properties = {
|
|
4315
|
+
...TeamsDialog.properties,
|
|
4316
|
+
contacts: { attribute: false },
|
|
4317
|
+
create: { attribute: false },
|
|
4318
|
+
selected: { state: true },
|
|
4319
|
+
name: { state: true },
|
|
4320
|
+
issue: { state: true }
|
|
4321
|
+
};
|
|
4322
|
+
constructor() {
|
|
4323
|
+
super();
|
|
4324
|
+
this.contacts = [];
|
|
4325
|
+
this.create = void 0;
|
|
4326
|
+
this.selected = [];
|
|
4327
|
+
this.name = "";
|
|
4328
|
+
this.issue = "";
|
|
4329
|
+
}
|
|
4330
|
+
willUpdate(changed) {
|
|
4331
|
+
if (changed.has("open") && this.open) {
|
|
4332
|
+
this.selected = [];
|
|
4333
|
+
this.name = "";
|
|
4334
|
+
this.issue = "";
|
|
4335
|
+
}
|
|
4336
|
+
}
|
|
4337
|
+
submit(event) {
|
|
4338
|
+
event.preventDefault();
|
|
4339
|
+
if (this.selected.length === 0) {
|
|
4340
|
+
this.issue = "Pick at least one person.";
|
|
4341
|
+
return;
|
|
4342
|
+
}
|
|
4343
|
+
if (!this.create?.(this.selected, this.selected.length > 1 ? this.name : ""))
|
|
4344
|
+
this.issue = "The chat could not be started.";
|
|
4345
|
+
}
|
|
4346
|
+
render() {
|
|
4347
|
+
const group = this.selected.length > 1;
|
|
4348
|
+
return this.frame(
|
|
4349
|
+
"New chat",
|
|
4350
|
+
html`<form @submit=${this.submit}>
|
|
4351
|
+
<div class="field">
|
|
4352
|
+
To
|
|
4353
|
+
<office-ui-people-picker
|
|
4354
|
+
label="People to chat with"
|
|
4355
|
+
.contacts=${this.contacts}
|
|
4356
|
+
.selected=${this.selected}
|
|
4357
|
+
@office-people-change=${(e) => {
|
|
4358
|
+
this.selected = e.detail.selected.slice(0, MAX_CHAT_MEMBERS - 1);
|
|
4359
|
+
this.issue = "";
|
|
4360
|
+
}}
|
|
4361
|
+
></office-ui-people-picker>
|
|
4362
|
+
</div>
|
|
4363
|
+
${group ? html`<label
|
|
4364
|
+
>Group name (optional)<input
|
|
4365
|
+
maxlength=${MAX_CHANNEL_NAME_CHARS}
|
|
4366
|
+
.value=${this.name}
|
|
4367
|
+
placeholder="Name this group chat"
|
|
4368
|
+
@input=${(e) => this.name = e.target.value}
|
|
4369
|
+
/></label>` : nothing}
|
|
4370
|
+
<small
|
|
4371
|
+
>${group ? "Everyone you pick joins one group chat. Only its members can read it." : "Pick one person for a 1:1 chat, or several for a group chat."}</small
|
|
4372
|
+
>
|
|
4373
|
+
${this.issue ? html`<p class="issue" role="alert">${this.issue}</p>` : nothing}
|
|
4374
|
+
<footer>
|
|
4375
|
+
<button type="button" @click=${this.requestClose}>Cancel</button>
|
|
4376
|
+
<button type="submit" class="primary" ?disabled=${this.selected.length === 0}>
|
|
4377
|
+
${group ? "Start group chat" : "Start chat"}
|
|
4378
|
+
</button>
|
|
4379
|
+
</footer>
|
|
4380
|
+
</form>`
|
|
4381
|
+
);
|
|
4382
|
+
}
|
|
4383
|
+
};
|
|
4384
|
+
function defineTeamsNewChatDialog(registry = globalThis.customElements) {
|
|
4385
|
+
if (registry && !registry.get("teams-new-chat-dialog"))
|
|
4386
|
+
registry.define("teams-new-chat-dialog", TeamsNewChatDialog);
|
|
4387
|
+
}
|
|
4388
|
+
|
|
4389
|
+
// raw-css:/home/runner/work/ooxml/ooxml/src/ui/src/teams/app/chat-people-dialog.css?raw
|
|
4390
|
+
var chat_people_dialog_default = "h3 {\n margin: var(--office-space-2) 0 0;\n font-size: var(--office-font-size);\n}\n.rename {\n display: grid;\n grid-template-columns: minmax(0, 1fr) auto;\n align-items: end;\n gap: var(--office-space-2);\n padding: 0;\n}\n.members {\n display: grid;\n gap: var(--office-space-1);\n margin: 0;\n padding: 0;\n list-style: none;\n}\n.members li {\n display: flex;\n align-items: center;\n gap: var(--office-space-3);\n padding: var(--office-space-1) 0;\n}\n.name {\n flex: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\noffice-ui-people-picker {\n font-weight: normal;\n}\n";
|
|
4391
|
+
|
|
4392
|
+
// src/teams/app/chat-people-dialog.ts
|
|
4393
|
+
var TeamsChatPeopleDialog = class extends TeamsDialog {
|
|
4394
|
+
static styles = dialogStyles(chat_people_dialog_default);
|
|
4395
|
+
static properties = {
|
|
4396
|
+
...TeamsDialog.properties,
|
|
4397
|
+
chat: { attribute: false },
|
|
4398
|
+
contacts: { attribute: false },
|
|
4399
|
+
name: { state: true },
|
|
4400
|
+
adding: { state: true }
|
|
4401
|
+
};
|
|
4402
|
+
constructor() {
|
|
4403
|
+
super();
|
|
4404
|
+
this.chat = null;
|
|
4405
|
+
this.contacts = [];
|
|
4406
|
+
this.name = "";
|
|
4407
|
+
this.adding = [];
|
|
4408
|
+
}
|
|
4409
|
+
willUpdate(changed) {
|
|
4410
|
+
if (changed.has("open") && this.open) {
|
|
4411
|
+
this.name = this.chat?.name ?? "";
|
|
4412
|
+
this.adding = [];
|
|
4413
|
+
}
|
|
4414
|
+
}
|
|
4415
|
+
render() {
|
|
4416
|
+
const chat = this.chat;
|
|
4417
|
+
if (!chat) return this.frame("People", html``);
|
|
4418
|
+
const group = chat.kind === "group";
|
|
4419
|
+
return this.frame(
|
|
4420
|
+
"People",
|
|
4421
|
+
html`<div class="body">
|
|
4422
|
+
${group ? html`<form
|
|
4423
|
+
class="rename"
|
|
4424
|
+
@submit=${(e) => {
|
|
4425
|
+
e.preventDefault();
|
|
4426
|
+
this.fire("teams-chat-rename", { id: chat.id, name: this.name });
|
|
4427
|
+
}}
|
|
4428
|
+
>
|
|
4429
|
+
<label
|
|
4430
|
+
>Group name<input
|
|
4431
|
+
maxlength=${MAX_CHANNEL_NAME_CHARS}
|
|
4432
|
+
.value=${this.name}
|
|
4433
|
+
placeholder="Name this group chat"
|
|
4434
|
+
@input=${(e) => this.name = e.target.value}
|
|
4435
|
+
/></label>
|
|
4436
|
+
<button type="submit">Rename</button>
|
|
4437
|
+
</form>` : nothing}
|
|
4438
|
+
<h3>In this chat (${chat.members.length})</h3>
|
|
4439
|
+
<ul class="members">
|
|
4440
|
+
${chat.members.map(
|
|
4441
|
+
(m) => html`<li>
|
|
4442
|
+
<office-ui-avatar
|
|
4443
|
+
size="sm"
|
|
4444
|
+
name=${m.name}
|
|
4445
|
+
seed=${m.id}
|
|
4446
|
+
presence=${m.availability}
|
|
4447
|
+
></office-ui-avatar>
|
|
4448
|
+
<span class="name">${m.name}${m.self ? " (you)" : ""}</span>
|
|
4449
|
+
${group && !m.self && chat.members.length > 1 ? html`<button
|
|
4450
|
+
type="button"
|
|
4451
|
+
aria-label=${`Remove ${m.name}`}
|
|
4452
|
+
@click=${() => this.fire("teams-chat-remove", { id: chat.id, userId: m.id })}
|
|
4453
|
+
>
|
|
4454
|
+
Remove
|
|
4455
|
+
</button>` : nothing}
|
|
4456
|
+
</li>`
|
|
4457
|
+
)}
|
|
4458
|
+
</ul>
|
|
4459
|
+
${group ? html`<h3>Add people</h3>
|
|
4460
|
+
<office-ui-people-picker
|
|
4461
|
+
label="People to add"
|
|
4462
|
+
.contacts=${this.contacts}
|
|
4463
|
+
.exclude=${chat.members.map((m) => m.id)}
|
|
4464
|
+
.selected=${this.adding}
|
|
4465
|
+
@office-people-change=${(e) => this.adding = e.detail.selected}
|
|
4466
|
+
></office-ui-people-picker>
|
|
4467
|
+
<footer>
|
|
4468
|
+
<button
|
|
4469
|
+
type="button"
|
|
4470
|
+
class="primary"
|
|
4471
|
+
?disabled=${this.adding.length === 0}
|
|
4472
|
+
@click=${() => {
|
|
4473
|
+
this.fire("teams-chat-add", { id: chat.id, userIds: this.adding });
|
|
4474
|
+
this.adding = [];
|
|
4475
|
+
}}
|
|
4476
|
+
>
|
|
4477
|
+
Add to chat
|
|
4478
|
+
</button>
|
|
4479
|
+
</footer>` : html`<p>
|
|
4480
|
+
People cannot be added to or removed from a 1:1 chat. Start a group chat instead.
|
|
4481
|
+
</p>`}
|
|
4482
|
+
<footer>
|
|
4483
|
+
${chat.canLeave ? html`<button
|
|
4484
|
+
type="button"
|
|
4485
|
+
class="danger"
|
|
4486
|
+
@click=${() => this.fire("teams-chat-leave", { id: chat.id })}
|
|
4487
|
+
>
|
|
4488
|
+
Leave chat
|
|
4489
|
+
</button>` : nothing}
|
|
4490
|
+
<button type="button" @click=${this.requestClose}>Done</button>
|
|
4491
|
+
</footer>
|
|
4492
|
+
</div>`
|
|
4493
|
+
);
|
|
4494
|
+
}
|
|
4495
|
+
};
|
|
4496
|
+
function defineTeamsChatPeopleDialog(registry = globalThis.customElements) {
|
|
4497
|
+
if (registry && !registry.get("teams-chat-people-dialog"))
|
|
4498
|
+
registry.define("teams-chat-people-dialog", TeamsChatPeopleDialog);
|
|
4499
|
+
}
|
|
4500
|
+
|
|
4501
|
+
// raw-css:/home/runner/work/ooxml/ooxml/src/ui/src/teams/app/meeting-dialog.css?raw
|
|
4502
|
+
var meeting_dialog_default = ".times {\n display: grid;\n grid-template-columns: repeat(2, minmax(0, 1fr));\n gap: var(--office-space-3);\n}\noffice-ui-people-picker {\n font-weight: normal;\n}\n@media (max-width: 40em) {\n .times {\n grid-template-columns: minmax(0, 1fr);\n }\n}\n";
|
|
4503
|
+
|
|
4504
|
+
// src/teams/app/meeting-dialog.ts
|
|
4505
|
+
var SLOT = 30 * MINUTE_MS;
|
|
4506
|
+
var NOT_SAVED = "The meeting was not saved. Your details are kept here.";
|
|
4507
|
+
function toLocalInput(ms) {
|
|
4508
|
+
const d = new Date(ms);
|
|
4509
|
+
const p = (n) => String(n).padStart(2, "0");
|
|
4510
|
+
return `${d.getFullYear()}-${p(d.getMonth() + 1)}-${p(d.getDate())}T${p(d.getHours())}:${p(d.getMinutes())}`;
|
|
4511
|
+
}
|
|
4512
|
+
var TeamsMeetingDialog = class extends TeamsDialog {
|
|
4513
|
+
static styles = dialogStyles(meeting_dialog_default);
|
|
4514
|
+
static properties = {
|
|
4515
|
+
...TeamsDialog.properties,
|
|
4516
|
+
meeting: { attribute: false },
|
|
4517
|
+
start: { type: Number },
|
|
4518
|
+
occurrence: { type: Number },
|
|
4519
|
+
contacts: { attribute: false },
|
|
4520
|
+
channels: { attribute: false },
|
|
4521
|
+
save: { attribute: false },
|
|
4522
|
+
meetingTitle: { state: true },
|
|
4523
|
+
description: { state: true },
|
|
4524
|
+
startText: { state: true },
|
|
4525
|
+
endText: { state: true },
|
|
4526
|
+
repeat: { state: true },
|
|
4527
|
+
endMode: { state: true },
|
|
4528
|
+
untilText: { state: true },
|
|
4529
|
+
countText: { state: true },
|
|
4530
|
+
channelId: { state: true },
|
|
4531
|
+
attendees: { state: true },
|
|
4532
|
+
issue: { state: true }
|
|
4533
|
+
};
|
|
4534
|
+
constructor() {
|
|
4535
|
+
super();
|
|
4536
|
+
this.meeting = null;
|
|
4537
|
+
this.start = 0;
|
|
4538
|
+
this.occurrence = 0;
|
|
4539
|
+
this.contacts = [];
|
|
4540
|
+
this.channels = [];
|
|
4541
|
+
this.save = void 0;
|
|
4542
|
+
this.meetingTitle = "";
|
|
4543
|
+
this.description = "";
|
|
4544
|
+
this.startText = "";
|
|
4545
|
+
this.endText = "";
|
|
4546
|
+
this.repeat = "none";
|
|
4547
|
+
this.endMode = "never";
|
|
4548
|
+
this.untilText = "";
|
|
4549
|
+
this.countText = "10";
|
|
4550
|
+
this.channelId = "";
|
|
4551
|
+
this.attendees = [];
|
|
4552
|
+
this.issue = "";
|
|
4553
|
+
}
|
|
4554
|
+
willUpdate(changed) {
|
|
4555
|
+
if (!changed.has("open") || !this.open) return;
|
|
4556
|
+
const m = this.meeting;
|
|
4557
|
+
const one = m && this.occurrence ? occurrenceAt(m, this.start || m.start) : null;
|
|
4558
|
+
const begin = one?.start ?? m?.start ?? (this.start || Math.ceil(Date.now() / SLOT) * SLOT);
|
|
4559
|
+
this.meetingTitle = one?.title ?? m?.title ?? "";
|
|
4560
|
+
this.description = one?.description ?? m?.description ?? "";
|
|
4561
|
+
this.startText = toLocalInput(begin);
|
|
4562
|
+
this.endText = toLocalInput(one?.end ?? m?.end ?? begin + SLOT);
|
|
4563
|
+
this.repeat = m?.repeat ?? "none";
|
|
4564
|
+
this.endMode = m?.count !== void 0 ? "count" : m?.until !== void 0 ? "date" : "never";
|
|
4565
|
+
this.countText = String(m?.count ?? 10);
|
|
4566
|
+
this.untilText = toLocalInput(m?.until ?? begin + 28 * 864e5).slice(0, 10);
|
|
4567
|
+
this.channelId = m?.channelId ?? "";
|
|
4568
|
+
this.attendees = m?.attendees.map((a) => a.id) ?? [];
|
|
4569
|
+
this.issue = "";
|
|
4570
|
+
}
|
|
4571
|
+
moveStart(value) {
|
|
4572
|
+
const before = new Date(this.startText).getTime();
|
|
4573
|
+
const after = new Date(value).getTime();
|
|
4574
|
+
const end = new Date(this.endText).getTime();
|
|
4575
|
+
this.startText = value;
|
|
4576
|
+
if (Number.isFinite(before) && Number.isFinite(after) && Number.isFinite(end))
|
|
4577
|
+
this.endText = toLocalInput(end + (after - before));
|
|
4578
|
+
this.issue = "";
|
|
4579
|
+
}
|
|
4580
|
+
validCount() {
|
|
4581
|
+
const n = Number(this.countText);
|
|
4582
|
+
return Number.isInteger(n) && n >= 1 && n <= MAX_RECURRENCE_COUNT;
|
|
4583
|
+
}
|
|
4584
|
+
untilTime() {
|
|
4585
|
+
return (/* @__PURE__ */ new Date(`${this.untilText}T23:59:59.999`)).getTime();
|
|
4586
|
+
}
|
|
4587
|
+
validUntil(start) {
|
|
4588
|
+
const until = this.untilTime();
|
|
4589
|
+
return Number.isFinite(until) && until >= start;
|
|
4590
|
+
}
|
|
4591
|
+
/** The end of the repeat to store: a count, the end of a day, or none (null clears an old end). */
|
|
4592
|
+
recurrenceEnd() {
|
|
4593
|
+
if (this.repeat === "none" || this.endMode === "never") return { count: null, until: null };
|
|
4594
|
+
return this.endMode === "count" ? { count: Number(this.countText), until: null } : { count: null, until: this.untilTime() };
|
|
4595
|
+
}
|
|
4596
|
+
submit(event) {
|
|
4597
|
+
event.preventDefault();
|
|
4598
|
+
const start = new Date(this.startText).getTime();
|
|
4599
|
+
const end = new Date(this.endText).getTime();
|
|
4600
|
+
if (!this.meetingTitle.trim()) this.issue = "Add a title.";
|
|
4601
|
+
else if (!Number.isFinite(start) || !Number.isFinite(end)) this.issue = "Pick a start and end.";
|
|
4602
|
+
else if (end <= start) this.issue = "The meeting must end after it starts.";
|
|
4603
|
+
else if (end - start > 24 * 60 * MINUTE_MS) this.issue = "A meeting can last at most 24 hours.";
|
|
4604
|
+
else if (this.occurrence) {
|
|
4605
|
+
const one = { title: this.meetingTitle, description: this.description, start, end };
|
|
4606
|
+
if (!this.save?.(one, this.meeting?.id, this.occurrence)) this.issue = NOT_SAVED;
|
|
4607
|
+
} else if (this.repeat !== "none" && this.endMode === "count" && !this.validCount())
|
|
4608
|
+
this.issue = `Enter a number of events from 1 to ${MAX_RECURRENCE_COUNT}.`;
|
|
4609
|
+
else if (this.repeat !== "none" && this.endMode === "date" && !this.validUntil(start))
|
|
4610
|
+
this.issue = "The series must end on or after its first event.";
|
|
4611
|
+
else if (!this.save?.(
|
|
4612
|
+
{
|
|
4613
|
+
title: this.meetingTitle,
|
|
4614
|
+
description: this.description,
|
|
4615
|
+
start,
|
|
4616
|
+
end,
|
|
4617
|
+
repeat: this.repeat,
|
|
4618
|
+
...this.recurrenceEnd(),
|
|
4619
|
+
attendeeIds: this.channelId ? [] : this.attendees,
|
|
4620
|
+
...this.channelId ? { channelId: this.channelId } : {}
|
|
4621
|
+
},
|
|
4622
|
+
this.meeting?.id
|
|
4623
|
+
))
|
|
4624
|
+
this.issue = NOT_SAVED;
|
|
4625
|
+
}
|
|
4626
|
+
render() {
|
|
4627
|
+
const editing = this.meeting !== null;
|
|
4628
|
+
const single = this.occurrence !== 0;
|
|
4629
|
+
return this.frame(
|
|
4630
|
+
single ? "Edit this event" : editing ? "Edit meeting" : "New meeting",
|
|
4631
|
+
html`<form @submit=${this.submit}>
|
|
4632
|
+
<label
|
|
4633
|
+
>Title<input
|
|
4634
|
+
maxlength=${MAX_MEETING_TITLE}
|
|
4635
|
+
.value=${this.meetingTitle}
|
|
4636
|
+
placeholder="Add a title"
|
|
4637
|
+
@input=${(e) => {
|
|
4638
|
+
this.meetingTitle = e.target.value;
|
|
4639
|
+
this.issue = "";
|
|
4640
|
+
}}
|
|
4641
|
+
/></label>
|
|
4642
|
+
<div class="times">
|
|
4643
|
+
<label
|
|
4644
|
+
>Start<input
|
|
4645
|
+
type="datetime-local"
|
|
4646
|
+
.value=${this.startText}
|
|
4647
|
+
@change=${(e) => this.moveStart(e.target.value)}
|
|
4648
|
+
/></label>
|
|
4649
|
+
<label
|
|
4650
|
+
>End<input
|
|
4651
|
+
type="datetime-local"
|
|
4652
|
+
.value=${this.endText}
|
|
4653
|
+
@change=${(e) => {
|
|
4654
|
+
this.endText = e.target.value;
|
|
4655
|
+
this.issue = "";
|
|
4656
|
+
}}
|
|
4657
|
+
/></label>
|
|
4658
|
+
</div>
|
|
4659
|
+
${single ? html`<small>Only this event changes. The rest of the series stays as it is.</small>` : html`
|
|
4660
|
+
<label
|
|
4661
|
+
>Repeat<select
|
|
4662
|
+
.value=${this.repeat}
|
|
4663
|
+
@change=${(e) => this.repeat = e.target.value}
|
|
4664
|
+
>
|
|
4665
|
+
<option value="none">Does not repeat</option>
|
|
4666
|
+
<option value="daily">Every day</option>
|
|
4667
|
+
<option value="weekly">Every week</option>
|
|
4668
|
+
</select></label
|
|
4669
|
+
>
|
|
4670
|
+
${this.repeat === "none" ? nothing : html`<label
|
|
4671
|
+
>Ends<select
|
|
4672
|
+
.value=${this.endMode}
|
|
4673
|
+
@change=${(e) => this.endMode = e.target.value}
|
|
4674
|
+
>
|
|
4675
|
+
<option value="never">Never</option>
|
|
4676
|
+
<option value="date">On a date</option>
|
|
4677
|
+
<option value="count">After a number of events</option>
|
|
4678
|
+
</select></label
|
|
4679
|
+
>
|
|
4680
|
+
${this.endMode === "date" ? html`<label
|
|
4681
|
+
>End date<input
|
|
4682
|
+
type="date"
|
|
4683
|
+
.value=${this.untilText}
|
|
4684
|
+
@change=${(e) => {
|
|
4685
|
+
this.untilText = e.target.value;
|
|
4686
|
+
this.issue = "";
|
|
4687
|
+
}}
|
|
4688
|
+
/></label>` : nothing}
|
|
4689
|
+
${this.endMode === "count" ? html`<label
|
|
4690
|
+
>Number of events<input
|
|
4691
|
+
type="number"
|
|
4692
|
+
min="1"
|
|
4693
|
+
max=${MAX_RECURRENCE_COUNT}
|
|
4694
|
+
.value=${this.countText}
|
|
4695
|
+
@input=${(e) => {
|
|
4696
|
+
this.countText = e.target.value;
|
|
4697
|
+
this.issue = "";
|
|
4698
|
+
}}
|
|
4699
|
+
/></label>` : nothing}`}
|
|
4700
|
+
<label
|
|
4701
|
+
>Channel (optional)<select
|
|
4702
|
+
?disabled=${editing}
|
|
4703
|
+
.value=${this.channelId}
|
|
4704
|
+
@change=${(e) => this.channelId = e.target.value}
|
|
4705
|
+
>
|
|
4706
|
+
<option value="">No channel: invite people</option>
|
|
4707
|
+
${this.channels.map((c) => html`<option value=${c.id}># ${c.name}</option>`)}
|
|
4708
|
+
</select></label
|
|
4709
|
+
>
|
|
4710
|
+
${this.channelId ? html`<small
|
|
4711
|
+
>A channel meeting posts a meeting card in the channel and shows in
|
|
4712
|
+
everyone's calendar.</small
|
|
4713
|
+
>` : html`<div class="field">
|
|
4714
|
+
Attendees
|
|
4715
|
+
<office-ui-people-picker
|
|
4716
|
+
label="Attendees"
|
|
4717
|
+
.contacts=${this.contacts}
|
|
4718
|
+
.selected=${this.attendees}
|
|
4719
|
+
@office-people-change=${(e) => this.attendees = e.detail.selected}
|
|
4720
|
+
></office-ui-people-picker>
|
|
4721
|
+
</div>`}
|
|
4722
|
+
`}
|
|
4723
|
+
<label
|
|
4724
|
+
>Details (optional)<textarea
|
|
4725
|
+
maxlength=${MAX_MEETING_DESCRIPTION}
|
|
4726
|
+
.value=${this.description}
|
|
4727
|
+
placeholder="Add an agenda or notes"
|
|
4728
|
+
@input=${(e) => this.description = e.target.value}
|
|
4729
|
+
></textarea>
|
|
4730
|
+
</label>
|
|
4731
|
+
<small
|
|
4732
|
+
>Times are shown in your time zone. The organizer's zone keeps repeats on schedule.</small
|
|
4733
|
+
>
|
|
4734
|
+
${this.issue ? html`<p class="issue" role="alert">${this.issue}</p>` : nothing}
|
|
4735
|
+
<footer>
|
|
4736
|
+
<button type="button" @click=${this.requestClose}>Cancel</button>
|
|
4737
|
+
<button type="submit" class="primary">${editing ? "Save" : "Send"}</button>
|
|
4738
|
+
</footer>
|
|
4739
|
+
</form>`
|
|
4740
|
+
);
|
|
4741
|
+
}
|
|
4742
|
+
};
|
|
4743
|
+
function defineTeamsMeetingDialog(registry = globalThis.customElements) {
|
|
4744
|
+
if (registry && !registry.get("teams-meeting-dialog"))
|
|
4745
|
+
registry.define("teams-meeting-dialog", TeamsMeetingDialog);
|
|
4746
|
+
}
|
|
4747
|
+
|
|
4748
|
+
// raw-css:/home/runner/work/ooxml/ooxml/src/ui/src/teams/app/meeting-details.css?raw
|
|
4749
|
+
var meeting_details_default = ".when {\n display: flex;\n align-items: center;\n gap: var(--office-space-2);\n color: var(--office-foreground);\n font-weight: var(--office-font-weight-bold);\n}\nh3 {\n margin: 0 0 var(--office-space-1);\n font-size: var(--office-font-size);\n}\n.people ul {\n margin: 0;\n padding-inline-start: var(--office-space-5);\n}\n.description {\n color: var(--office-foreground);\n white-space: pre-wrap;\n}\n.scope {\n display: grid;\n gap: var(--office-space-3);\n}\n.scope fieldset {\n display: grid;\n gap: var(--office-space-2);\n margin: 0;\n padding: var(--office-space-3);\n border: var(--office-border-width) solid var(--office-teams-divider);\n border-radius: var(--office-radius-md);\n}\n.scope label {\n display: flex;\n align-items: center;\n gap: var(--office-space-2);\n}\nfooter[hidden] {\n display: none;\n}\n";
|
|
4750
|
+
|
|
4751
|
+
// src/teams/app/meeting-details.ts
|
|
4752
|
+
var REPEAT_TEXT = { none: "", daily: "Repeats every day", weekly: "Repeats every week" };
|
|
4753
|
+
var TeamsMeetingDetails = class extends TeamsDialog {
|
|
4754
|
+
static styles = dialogStyles(meeting_details_default);
|
|
4755
|
+
static properties = {
|
|
4756
|
+
...TeamsDialog.properties,
|
|
4757
|
+
meeting: { attribute: false },
|
|
4758
|
+
occurrenceStart: { type: Number },
|
|
4759
|
+
zone: { type: String },
|
|
4760
|
+
channelName: { type: String },
|
|
4761
|
+
pending: { state: true },
|
|
4762
|
+
scope: { state: true }
|
|
4763
|
+
};
|
|
4764
|
+
constructor() {
|
|
4765
|
+
super();
|
|
4766
|
+
this.meeting = null;
|
|
4767
|
+
this.occurrenceStart = 0;
|
|
4768
|
+
this.zone = "";
|
|
4769
|
+
this.channelName = "";
|
|
4770
|
+
this.pending = null;
|
|
4771
|
+
this.scope = "occurrence";
|
|
4772
|
+
}
|
|
4773
|
+
willUpdate(changed) {
|
|
4774
|
+
if (changed.has("open") || changed.has("meeting") || changed.has("occurrenceStart"))
|
|
4775
|
+
this.pending = null;
|
|
4776
|
+
}
|
|
4777
|
+
emit(name) {
|
|
4778
|
+
if (this.meeting) this.fire(name, { meetingId: this.meeting.id });
|
|
4779
|
+
}
|
|
4780
|
+
recurrenceId() {
|
|
4781
|
+
const m = this.meeting;
|
|
4782
|
+
return m ? occurrenceAt(m, this.occurrenceStart || m.start)?.recurrenceId ?? m.start : 0;
|
|
4783
|
+
}
|
|
4784
|
+
/** Edit or cancel: a repeating meeting asks which events first. */
|
|
4785
|
+
change(action) {
|
|
4786
|
+
if (this.meeting?.repeat === "none") this.finish(action, "series");
|
|
4787
|
+
else {
|
|
4788
|
+
this.pending = action;
|
|
4789
|
+
this.scope = "occurrence";
|
|
4790
|
+
}
|
|
4791
|
+
}
|
|
4792
|
+
finish(action, scope) {
|
|
4793
|
+
if (!this.meeting) return;
|
|
4794
|
+
this.fire(`teams-meeting-${action}`, {
|
|
4795
|
+
meetingId: this.meeting.id,
|
|
4796
|
+
scope,
|
|
4797
|
+
recurrenceId: this.recurrenceId()
|
|
4798
|
+
});
|
|
4799
|
+
this.pending = null;
|
|
4800
|
+
}
|
|
4801
|
+
endText(m) {
|
|
4802
|
+
const date = (ms) => new Intl.DateTimeFormat([], {
|
|
4803
|
+
dateStyle: "medium",
|
|
4804
|
+
...this.zone ? { timeZone: this.zone } : {}
|
|
4805
|
+
}).format(ms);
|
|
4806
|
+
if (m.count !== void 0) return m.count === 1 ? ", 1 time" : `, ${m.count} times`;
|
|
4807
|
+
return m.until !== void 0 ? `, until ${date(m.until)}` : "";
|
|
4808
|
+
}
|
|
4809
|
+
scopeChoice(action) {
|
|
4810
|
+
const options = [
|
|
4811
|
+
["occurrence", action === "edit" ? "This event" : "This event only"],
|
|
4812
|
+
["series", action === "edit" ? "All events in the series" : "All events in the series"]
|
|
4813
|
+
];
|
|
4814
|
+
return html`<form
|
|
4815
|
+
class="scope"
|
|
4816
|
+
@submit=${(e) => {
|
|
4817
|
+
e.preventDefault();
|
|
4818
|
+
this.finish(action, this.scope);
|
|
4819
|
+
}}
|
|
4820
|
+
>
|
|
4821
|
+
<fieldset>
|
|
4822
|
+
<legend>
|
|
4823
|
+
${action === "edit" ? "Edit recurring meeting" : "Cancel recurring meeting"}
|
|
4824
|
+
</legend>
|
|
4825
|
+
${options.map(
|
|
4826
|
+
([value, label]) => html`<label
|
|
4827
|
+
><input
|
|
4828
|
+
type="radio"
|
|
4829
|
+
name="scope"
|
|
4830
|
+
.value=${value}
|
|
4831
|
+
.checked=${this.scope === value}
|
|
4832
|
+
@change=${() => this.scope = value}
|
|
4833
|
+
/>
|
|
4834
|
+
${label}</label
|
|
4835
|
+
>`
|
|
4836
|
+
)}
|
|
4837
|
+
</fieldset>
|
|
4838
|
+
<footer>
|
|
4839
|
+
<button type="button" @click=${() => this.pending = null}>Back</button>
|
|
4840
|
+
<button type="submit" class=${action === "cancel" ? "danger" : "primary"}>
|
|
4841
|
+
${action === "edit" ? "Continue" : "Cancel meeting"}
|
|
4842
|
+
</button>
|
|
4843
|
+
</footer>
|
|
4844
|
+
</form>`;
|
|
4845
|
+
}
|
|
4846
|
+
render() {
|
|
4847
|
+
const m = this.meeting;
|
|
4848
|
+
if (!m) return this.frame("Meeting", html``);
|
|
4849
|
+
const occurrence = occurrenceAt(m, this.occurrenceStart || m.start);
|
|
4850
|
+
const start = occurrence?.start ?? (this.occurrenceStart || m.start);
|
|
4851
|
+
const end = occurrence?.end ?? start + (m.end - m.start);
|
|
4852
|
+
const description = occurrence?.description ?? m.description;
|
|
4853
|
+
const hasChat = Boolean(m.chatId ?? m.channelId);
|
|
4854
|
+
return this.frame(
|
|
4855
|
+
occurrence?.title ?? m.title,
|
|
4856
|
+
html`<div class="body">
|
|
4857
|
+
<p class="when">${icon("calendar")} ${formatWhen(start, end)}</p>
|
|
4858
|
+
${m.repeat !== "none" ? html`<p>${REPEAT_TEXT[m.repeat]}${this.endText(m)}</p>` : nothing}
|
|
4859
|
+
${m.zone !== this.zone ? html`<p>Scheduled in the organizer's time zone, ${m.zone.replaceAll("_", " ")}.</p>` : nothing}
|
|
4860
|
+
<p>Organized by ${m.mine ? "you" : m.organizerName}</p>
|
|
4861
|
+
${m.channelId ? html`<p>
|
|
4862
|
+
Channel meeting in # ${this.channelName || "a channel"}. Everyone in the channel can
|
|
4863
|
+
join.
|
|
4864
|
+
</p>` : html`<div class="people">
|
|
4865
|
+
<h3>Attendees (${m.attendees.length + 1})</h3>
|
|
4866
|
+
<ul>
|
|
4867
|
+
<li>${m.organizerName} (organizer)</li>
|
|
4868
|
+
${m.attendees.map((a) => html`<li>${a.name}</li>`)}
|
|
4869
|
+
</ul>
|
|
4870
|
+
</div>`}
|
|
4871
|
+
${description ? html`<p class="description">${description}</p>` : nothing}
|
|
4872
|
+
${this.pending ? this.scopeChoice(this.pending) : nothing}
|
|
4873
|
+
<footer ?hidden=${this.pending !== null}>
|
|
4874
|
+
<button type="button" class="primary" @click=${() => this.emit("teams-meeting-join")}>
|
|
4875
|
+
${m.live ? "Join now" : "Join"}
|
|
4876
|
+
</button>
|
|
4877
|
+
${hasChat ? html`<button type="button" @click=${() => this.emit("teams-meeting-chat")}>
|
|
4878
|
+
Meeting chat
|
|
4879
|
+
</button>` : nothing}
|
|
4880
|
+
<button type="button" @click=${() => this.emit("teams-meeting-ics")}>Export .ics</button>
|
|
4881
|
+
${m.mine ? html`<button type="button" @click=${() => this.change("edit")}>Edit</button>
|
|
4882
|
+
<button type="button" class="danger" @click=${() => this.change("cancel")}>
|
|
4883
|
+
Cancel meeting
|
|
4884
|
+
</button>` : nothing}
|
|
4885
|
+
</footer>
|
|
4886
|
+
</div>`,
|
|
4887
|
+
"Close meeting details"
|
|
4888
|
+
);
|
|
4889
|
+
}
|
|
4890
|
+
};
|
|
4891
|
+
function defineTeamsMeetingDetails(registry = globalThis.customElements) {
|
|
4892
|
+
if (registry && !registry.get("teams-meeting-details"))
|
|
4893
|
+
registry.define("teams-meeting-details", TeamsMeetingDetails);
|
|
4894
|
+
}
|
|
4895
|
+
function chatHeader(chat, on) {
|
|
4896
|
+
const other = chat.kind === "direct" ? chat.members.find((m) => !m.self) : void 0;
|
|
4897
|
+
const online = chat.members.filter((m) => !m.self && m.availability !== "offline").length;
|
|
4898
|
+
return html`<header class="channel-head chat-head">
|
|
4899
|
+
<button
|
|
4900
|
+
type="button"
|
|
4901
|
+
class="back"
|
|
4902
|
+
aria-label="Back to chats"
|
|
4903
|
+
title="Back to chats"
|
|
4904
|
+
@click=${on.back}
|
|
4905
|
+
>
|
|
4906
|
+
${icon("back")}
|
|
4907
|
+
</button>
|
|
4908
|
+
${other ? html`<office-ui-avatar
|
|
4909
|
+
name=${other.name}
|
|
4910
|
+
seed=${other.id}
|
|
4911
|
+
presence=${other.availability}
|
|
4912
|
+
></office-ui-avatar>` : html`<span class="group-mark" aria-hidden="true"
|
|
4913
|
+
>${icon(chat.meetingId ? "calendar" : "users")}</span
|
|
4914
|
+
>`}
|
|
4915
|
+
<h1>${chat.title}</h1>
|
|
4916
|
+
<span class="topic"
|
|
4917
|
+
>${chat.kind === "direct" ? other?.availability ?? "" : `${chat.members.length} people${online ? `, ${online} online` : ""}`}</span
|
|
4918
|
+
>
|
|
4919
|
+
<div class="people" aria-label="People in this chat">
|
|
4920
|
+
${chat.members.slice(0, 5).map(
|
|
4921
|
+
(m) => html`<office-ui-avatar
|
|
4922
|
+
size="sm"
|
|
4923
|
+
name=${m.name}
|
|
4924
|
+
seed=${m.id}
|
|
4925
|
+
presence=${m.availability}
|
|
4926
|
+
></office-ui-avatar>`
|
|
4927
|
+
)}
|
|
4928
|
+
${chat.members.length > 5 ? html`<span class="more">+${chat.members.length - 5}</span>` : nothing}
|
|
4929
|
+
</div>
|
|
4930
|
+
<button type="button" class="chat-people" @click=${on.people}>${icon("users")} People</button>
|
|
4931
|
+
<button type="button" class="meet" @click=${on.call}>
|
|
4932
|
+
${chat.live ? "Join call" : "Call"}
|
|
4933
|
+
</button>
|
|
4934
|
+
</header>`;
|
|
4935
|
+
}
|
|
4936
|
+
function meetingCards(meetings, now) {
|
|
4937
|
+
const out = {};
|
|
4938
|
+
for (const m of meetings) {
|
|
4939
|
+
const next = occurrencesBetween(m, now, now + 400 * 864e5)[0];
|
|
4940
|
+
out[m.id] = {
|
|
4941
|
+
title: m.title,
|
|
4942
|
+
start: next?.start ?? m.start,
|
|
4943
|
+
end: next?.end ?? m.end,
|
|
4944
|
+
live: m.live
|
|
4945
|
+
};
|
|
4946
|
+
}
|
|
4947
|
+
return out;
|
|
4948
|
+
}
|
|
4949
|
+
|
|
4950
|
+
// src/teams/app/calendar-app.ts
|
|
4951
|
+
function downloadText(name, text, type = "text/calendar") {
|
|
4952
|
+
const doc = globalThis.document;
|
|
4953
|
+
if (!doc || typeof URL.createObjectURL !== "function") return false;
|
|
4954
|
+
const url = URL.createObjectURL(new Blob([text], { type: `${type};charset=utf-8` }));
|
|
4955
|
+
const link = doc.createElement("a");
|
|
4956
|
+
link.href = url;
|
|
4957
|
+
link.download = name;
|
|
4958
|
+
doc.body.append(link);
|
|
4959
|
+
link.click();
|
|
4960
|
+
link.remove();
|
|
4961
|
+
setTimeout(() => URL.revokeObjectURL(url), 1e3);
|
|
4962
|
+
return true;
|
|
4963
|
+
}
|
|
4964
|
+
|
|
3194
4965
|
// src/teams/app/teams-app.ts
|
|
3195
4966
|
var LOCAL_THEME = THEME_CSS.replaceAll(
|
|
3196
4967
|
':root[data-office-theme="dark"]',
|
|
3197
4968
|
':host([data-office-theme="dark"])'
|
|
3198
4969
|
).replaceAll(':root:not([data-office-theme="light"])', ':host([data-office-theme="system"])').replaceAll(":root", ":host([data-office-theme])");
|
|
3199
4970
|
var RAIL = [
|
|
4971
|
+
{ id: "activity", label: "Activity", icon: "bell" },
|
|
4972
|
+
{ id: "chat", label: "Chat", icon: "message" },
|
|
3200
4973
|
{ id: "teams", label: "Teams", icon: "users" },
|
|
3201
|
-
{ id: "
|
|
3202
|
-
{ id: "
|
|
3203
|
-
{ id: "
|
|
3204
|
-
{
|
|
4974
|
+
{ id: "calendar", label: "Calendar", icon: "calendar" },
|
|
4975
|
+
{ id: "calls", label: "Calls", icon: "phone", secondary: true },
|
|
4976
|
+
{ id: "files", label: "Files", icon: "folder", secondary: true },
|
|
4977
|
+
{
|
|
4978
|
+
id: "followed",
|
|
4979
|
+
label: "Followed threads",
|
|
4980
|
+
shortLabel: "Threads",
|
|
4981
|
+
icon: "chat",
|
|
4982
|
+
secondary: true
|
|
4983
|
+
},
|
|
4984
|
+
{ id: "drafts", label: "Drafts", icon: "chat", secondary: true }
|
|
3205
4985
|
];
|
|
3206
4986
|
var TeamsApp = class extends LitElement {
|
|
3207
4987
|
static styles = [unsafeCSS(LOCAL_THEME), unsafeCSS(teams_app_default)];
|
|
@@ -3217,13 +4997,20 @@ var TeamsApp = class extends LitElement {
|
|
|
3217
4997
|
preview: { state: true },
|
|
3218
4998
|
addingTab: { state: true },
|
|
3219
4999
|
creatingChannel: { state: true },
|
|
5000
|
+
newChat: { state: true },
|
|
5001
|
+
chatPeople: { state: true },
|
|
5002
|
+
meetingForm: { state: true },
|
|
5003
|
+
meetingDetails: { state: true },
|
|
3220
5004
|
rail: { state: true },
|
|
3221
5005
|
tab: { state: true },
|
|
3222
5006
|
panel: { state: true },
|
|
3223
5007
|
meeting: { state: true },
|
|
3224
5008
|
settingsOpen: { state: true },
|
|
3225
|
-
|
|
5009
|
+
mobileView: { state: true },
|
|
3226
5010
|
toast: { state: true },
|
|
5011
|
+
activityToasts: { state: true },
|
|
5012
|
+
activityFilter: { state: true },
|
|
5013
|
+
highlightId: { state: true },
|
|
3227
5014
|
identity: { state: true },
|
|
3228
5015
|
followedUnreadOnly: { state: true },
|
|
3229
5016
|
theme: { state: true },
|
|
@@ -3231,9 +5018,18 @@ var TeamsApp = class extends LitElement {
|
|
|
3231
5018
|
chatDensity: { state: true },
|
|
3232
5019
|
showAppNames: { state: true }
|
|
3233
5020
|
};
|
|
3234
|
-
teams = new TeamsController(
|
|
5021
|
+
teams = new TeamsController(
|
|
5022
|
+
this,
|
|
5023
|
+
(text) => this.notify(text),
|
|
5024
|
+
(item) => this.announce(item)
|
|
5025
|
+
);
|
|
3235
5026
|
toastTimer;
|
|
5027
|
+
activityToastTimers = /* @__PURE__ */ new Map();
|
|
5028
|
+
highlightTimer;
|
|
5029
|
+
stopActivity;
|
|
3236
5030
|
openRequest = 0;
|
|
5031
|
+
/** The channel last open in the Teams app, restored when you come back from Chat. */
|
|
5032
|
+
lastChannelId = "";
|
|
3237
5033
|
retainedTab;
|
|
3238
5034
|
themeStorageKey = "";
|
|
3239
5035
|
popoutRequested = new URL(globalThis.location?.href ?? "https://workspace.invalid").searchParams.get(
|
|
@@ -3256,13 +5052,20 @@ var TeamsApp = class extends LitElement {
|
|
|
3256
5052
|
this.retainedTab = void 0;
|
|
3257
5053
|
this.addingTab = false;
|
|
3258
5054
|
this.creatingChannel = false;
|
|
5055
|
+
this.newChat = false;
|
|
5056
|
+
this.chatPeople = false;
|
|
5057
|
+
this.meetingForm = null;
|
|
5058
|
+
this.meetingDetails = null;
|
|
3259
5059
|
this.rail = "teams";
|
|
3260
5060
|
this.tab = "posts";
|
|
3261
5061
|
this.panel = "";
|
|
3262
5062
|
this.meeting = false;
|
|
3263
5063
|
this.settingsOpen = false;
|
|
3264
|
-
this.
|
|
5064
|
+
this.mobileView = "conversation";
|
|
3265
5065
|
this.toast = "";
|
|
5066
|
+
this.activityToasts = [];
|
|
5067
|
+
this.activityFilter = "all";
|
|
5068
|
+
this.highlightId = "";
|
|
3266
5069
|
this.identity = null;
|
|
3267
5070
|
this.followedUnreadOnly = false;
|
|
3268
5071
|
this.theme = "system";
|
|
@@ -3284,9 +5087,14 @@ var TeamsApp = class extends LitElement {
|
|
|
3284
5087
|
defineTeamsChannelTab();
|
|
3285
5088
|
defineTeamsFilesPanel();
|
|
3286
5089
|
defineTeamsProfileMenu();
|
|
5090
|
+
defineTeamsPinnedBar();
|
|
3287
5091
|
defineTeamsAddTabDialog();
|
|
3288
|
-
defineTeamsNavigationDrawer();
|
|
3289
5092
|
defineTeamsCreateChannelDialog();
|
|
5093
|
+
defineTeamsNewChatDialog();
|
|
5094
|
+
defineTeamsChatPeopleDialog();
|
|
5095
|
+
defineTeamsMeetingDialog();
|
|
5096
|
+
defineTeamsMeetingDetails();
|
|
5097
|
+
this.stopActivity = watchActivity(this.ownerDocument, () => this.teams.client?.noteActivity());
|
|
3290
5098
|
super.connectedCallback();
|
|
3291
5099
|
}
|
|
3292
5100
|
// ---- lifecycle --------------------------------------------------------------------------
|
|
@@ -3315,7 +5123,8 @@ var TeamsApp = class extends LitElement {
|
|
|
3315
5123
|
this.tab = "posts";
|
|
3316
5124
|
this.addingTab = false;
|
|
3317
5125
|
this.creatingChannel = false;
|
|
3318
|
-
this.
|
|
5126
|
+
this.newChat = this.chatPeople = false;
|
|
5127
|
+
this.meetingForm = this.meetingDetails = null;
|
|
3319
5128
|
this.settingsOpen = false;
|
|
3320
5129
|
this.openRequest++;
|
|
3321
5130
|
const named = this.userName ? { id: this.userId || loadIdentity()?.id || crypto.randomUUID(), name: this.userName } : this.identity ?? loadIdentity();
|
|
@@ -3344,6 +5153,8 @@ var TeamsApp = class extends LitElement {
|
|
|
3344
5153
|
updated() {
|
|
3345
5154
|
this.setAttribute("data-chat-density", this.chatDensity);
|
|
3346
5155
|
const state = this.teams.state;
|
|
5156
|
+
if (state?.channels.some((c) => c.id === state.selectedChannelId))
|
|
5157
|
+
this.lastChannelId = state.selectedChannelId;
|
|
3347
5158
|
if (state?.thread && document.visibilityState === "visible" && this.renderRoot.querySelector(".thread-pane"))
|
|
3348
5159
|
this.teams.client?.markThreadRead(state.selectedChannelId, state.thread.root.id);
|
|
3349
5160
|
}
|
|
@@ -3352,6 +5163,25 @@ var TeamsApp = class extends LitElement {
|
|
|
3352
5163
|
clearTimeout(this.toastTimer);
|
|
3353
5164
|
this.toastTimer = setTimeout(() => this.toast = "", 4e3);
|
|
3354
5165
|
}
|
|
5166
|
+
/** Deliver a notification the core allowed: a toast in a visible tab, else a desktop one. */
|
|
5167
|
+
announce(item) {
|
|
5168
|
+
const settings = this.teams.client?.getState().notificationSettings;
|
|
5169
|
+
if (!settings) return;
|
|
5170
|
+
deliverNotification(item, settings, browserDeliveryEnv(), {
|
|
5171
|
+
toast: (entry) => {
|
|
5172
|
+
this.activityToasts = [
|
|
5173
|
+
entry,
|
|
5174
|
+
...this.activityToasts.filter((t) => t.id !== entry.id)
|
|
5175
|
+
].slice(0, 3);
|
|
5176
|
+
clearTimeout(this.activityToastTimers.get(entry.id));
|
|
5177
|
+
this.activityToastTimers.set(
|
|
5178
|
+
entry.id,
|
|
5179
|
+
setTimeout(() => this.dismissToast(entry.id), 6e3)
|
|
5180
|
+
);
|
|
5181
|
+
},
|
|
5182
|
+
open: (entry) => entry.kind === "meeting" ? this.openMeeting(entry.messageId) : void this.openActivity(entry.id)
|
|
5183
|
+
});
|
|
5184
|
+
}
|
|
3355
5185
|
// ---- intent -> client actions -----------------------------------------------------------
|
|
3356
5186
|
async openFile(a, mode) {
|
|
3357
5187
|
if (!this.canLeaveContent()) return;
|
|
@@ -3423,6 +5253,11 @@ var TeamsApp = class extends LitElement {
|
|
|
3423
5253
|
this.openRequest++;
|
|
3424
5254
|
this.preview = null;
|
|
3425
5255
|
clearTimeout(this.toastTimer);
|
|
5256
|
+
for (const timer of this.activityToastTimers.values()) clearTimeout(timer);
|
|
5257
|
+
this.activityToastTimers.clear();
|
|
5258
|
+
clearTimeout(this.highlightTimer);
|
|
5259
|
+
this.stopActivity?.();
|
|
5260
|
+
this.stopActivity = void 0;
|
|
3426
5261
|
super.disconnectedCallback();
|
|
3427
5262
|
}
|
|
3428
5263
|
createChannel() {
|
|
@@ -3436,7 +5271,7 @@ var TeamsApp = class extends LitElement {
|
|
|
3436
5271
|
this.tab = "posts";
|
|
3437
5272
|
this.rail = "teams";
|
|
3438
5273
|
this.meeting = false;
|
|
3439
|
-
|
|
5274
|
+
this.mobileView = "conversation";
|
|
3440
5275
|
void this.focusCreatedChannel();
|
|
3441
5276
|
return true;
|
|
3442
5277
|
}
|
|
@@ -3465,9 +5300,10 @@ var TeamsApp = class extends LitElement {
|
|
|
3465
5300
|
startMeeting(channelId) {
|
|
3466
5301
|
if (!this.closePreview()) return;
|
|
3467
5302
|
void this.teams.client?.openCall(channelId);
|
|
3468
|
-
|
|
5303
|
+
this.mobileView = "conversation";
|
|
3469
5304
|
this.meeting = true;
|
|
3470
|
-
|
|
5305
|
+
const target = channelId ?? this.teams.state?.selectedChannelId;
|
|
5306
|
+
this.rail = this.teams.state?.chats.some((c) => c.id === target) ? "chat" : "teams";
|
|
3471
5307
|
}
|
|
3472
5308
|
selectChannel(id) {
|
|
3473
5309
|
if (!this.closePreview()) return false;
|
|
@@ -3478,27 +5314,11 @@ var TeamsApp = class extends LitElement {
|
|
|
3478
5314
|
this.teams.client?.search("");
|
|
3479
5315
|
this.meeting = false;
|
|
3480
5316
|
this.tab = "posts";
|
|
3481
|
-
this.rail = "teams";
|
|
3482
|
-
|
|
5317
|
+
this.rail = this.teams.state?.chats.some((c) => c.id === id) ? "chat" : "teams";
|
|
5318
|
+
this.mobileView = "conversation";
|
|
3483
5319
|
return true;
|
|
3484
5320
|
}
|
|
3485
|
-
async closeNavigation(navigated = false) {
|
|
3486
|
-
if (!this.navigationOpen) return;
|
|
3487
|
-
this.navigationOpen = false;
|
|
3488
|
-
await this.updateComplete;
|
|
3489
|
-
const drawer = this.renderRoot.querySelector("teams-navigation-drawer");
|
|
3490
|
-
await drawer?.updateComplete;
|
|
3491
|
-
if (this.navigationOpen || !this.isConnected) return;
|
|
3492
|
-
const trigger = this.renderRoot.querySelector("[data-open-navigation]");
|
|
3493
|
-
const heading = this.renderRoot.querySelector("main h1") ?? this.renderRoot.querySelector("main");
|
|
3494
|
-
if (!navigated && trigger?.getClientRects().length) trigger.focus();
|
|
3495
|
-
else if (heading) {
|
|
3496
|
-
heading.tabIndex = -1;
|
|
3497
|
-
heading.focus();
|
|
3498
|
-
}
|
|
3499
|
-
}
|
|
3500
5321
|
askSettings() {
|
|
3501
|
-
this.navigationOpen = false;
|
|
3502
5322
|
this.settingsOpen = true;
|
|
3503
5323
|
}
|
|
3504
5324
|
async closeSettings() {
|
|
@@ -3511,6 +5331,11 @@ var TeamsApp = class extends LitElement {
|
|
|
3511
5331
|
if (this.theme === "system") this.removeAttribute("data-office-theme");
|
|
3512
5332
|
else this.setAttribute("data-office-theme", this.theme);
|
|
3513
5333
|
}
|
|
5334
|
+
/** Which screen the compact shell shows: the channel or call list, or the content itself. */
|
|
5335
|
+
mobileScreen(s) {
|
|
5336
|
+
const listed = ["teams", "calls", "activity", "chat", "calendar"].includes(this.rail);
|
|
5337
|
+
return listed && this.mobileView === "list" && !(this.meeting && s.call) ? "list" : "content";
|
|
5338
|
+
}
|
|
3514
5339
|
// ---- template ---------------------------------------------------------------------------
|
|
3515
5340
|
render() {
|
|
3516
5341
|
if (this.popoutRequested)
|
|
@@ -3525,6 +5350,7 @@ var TeamsApp = class extends LitElement {
|
|
|
3525
5350
|
return html`
|
|
3526
5351
|
<div
|
|
3527
5352
|
class="shell"
|
|
5353
|
+
data-mobile-view=${this.mobileScreen(s)}
|
|
3528
5354
|
@office-chat-open-tab=${(event) => {
|
|
3529
5355
|
if (this.teams.state?.tabs.some((entry) => entry.id === event.detail.tabId))
|
|
3530
5356
|
this.selectTab(event.detail.tabId);
|
|
@@ -3535,13 +5361,15 @@ var TeamsApp = class extends LitElement {
|
|
|
3535
5361
|
<div class="body">
|
|
3536
5362
|
<office-ui-app-rail
|
|
3537
5363
|
.hideLabels=${!this.showAppNames}
|
|
3538
|
-
.items=${RAIL.map((i) => ({ ...i, ...i.id === "calls" && s.channels.some((c) => c.live) ? { badge: s.channels.filter((c) => c.live).length } : {} }))}
|
|
5364
|
+
.items=${RAIL.map((i) => ({ ...i, ...i.id === "calls" && s.channels.some((c) => c.live) ? { badge: s.channels.filter((c) => c.live).length } : {}, ...i.id === "activity" && s.activityUnread ? { badge: s.activityUnread } : {}, ...i.id === "chat" && s.chats.some((c) => c.unread) ? { badge: s.chats.reduce((n, c) => n + c.unread, 0) } : {} }))}
|
|
3539
5365
|
selected=${this.rail}
|
|
3540
5366
|
@office-rail-select=${(e) => {
|
|
3541
5367
|
if (!this.closePreview()) return;
|
|
3542
5368
|
this.settingsOpen = false;
|
|
5369
|
+
if (e.detail.id === "teams") this.leaveChatSelection();
|
|
3543
5370
|
this.rail = e.detail.id;
|
|
3544
5371
|
this.meeting = false;
|
|
5372
|
+
this.mobileView = "list";
|
|
3545
5373
|
}}
|
|
3546
5374
|
></office-ui-app-rail>
|
|
3547
5375
|
<aside class="side" ?inert=${this.settingsOpen}>${this.sidebar(s)}</aside>
|
|
@@ -3579,6 +5407,8 @@ var TeamsApp = class extends LitElement {
|
|
|
3579
5407
|
);
|
|
3580
5408
|
}}
|
|
3581
5409
|
.followSettings=${s.threadFollowSettings}
|
|
5410
|
+
.notificationSettings=${s.notificationSettings}
|
|
5411
|
+
@teams-settings-notifications=${(event) => this.teams.client?.setNotificationSettings(event.detail)}
|
|
3582
5412
|
.userName=${s.user.name}
|
|
3583
5413
|
@teams-settings-theme=${(event) => {
|
|
3584
5414
|
if (!["system", "light", "dark"].includes(event.detail.theme)) return;
|
|
@@ -3608,15 +5438,9 @@ var TeamsApp = class extends LitElement {
|
|
|
3608
5438
|
.create=${(name, description) => this.commitChannel(name, description, this.client)}
|
|
3609
5439
|
@teams-create-channel-close=${() => this.creatingChannel = false}
|
|
3610
5440
|
></teams-create-channel-dialog>
|
|
3611
|
-
<teams-navigation-drawer
|
|
3612
|
-
.heading=${this.rail === "calls" ? "Calls" : "Teams and channels"}
|
|
3613
|
-
?open=${this.navigationOpen}
|
|
3614
|
-
@teams-navigation-close=${() => void this.closeNavigation()}
|
|
3615
|
-
>
|
|
3616
|
-
${this.navigationOpen ? this.sidebar(s) : nothing}
|
|
3617
|
-
</teams-navigation-drawer>
|
|
3618
5441
|
${this.toast ? html`<div class="toast" role="status">${this.toast}</div>` : nothing}
|
|
3619
|
-
|
|
5442
|
+
${this.activityToasts.length ? html`<div class="activity-toasts">${this.activityToasts.map((t) => this.activityToastView(t))}</div>` : nothing}
|
|
5443
|
+
${this.chatDialogs(s)} ${this.calendarDialogs(s)}
|
|
3620
5444
|
<teams-add-tab-dialog
|
|
3621
5445
|
.open=${this.addingTab}
|
|
3622
5446
|
.client=${this.teams.client}
|
|
@@ -3673,21 +5497,7 @@ var TeamsApp = class extends LitElement {
|
|
|
3673
5497
|
topbar(s) {
|
|
3674
5498
|
return html`
|
|
3675
5499
|
<header class="topbar">
|
|
3676
|
-
<div class="brand">
|
|
3677
|
-
<button
|
|
3678
|
-
type="button"
|
|
3679
|
-
class="navigation-toggle"
|
|
3680
|
-
data-open-navigation
|
|
3681
|
-
aria-label="Open navigation"
|
|
3682
|
-
title="Open navigation"
|
|
3683
|
-
aria-haspopup="dialog"
|
|
3684
|
-
aria-expanded=${String(this.navigationOpen)}
|
|
3685
|
-
@click=${() => this.navigationOpen = true}
|
|
3686
|
-
>
|
|
3687
|
-
${icon("navigation")}
|
|
3688
|
-
</button>
|
|
3689
|
-
<span class="logo">T</span><span>Teams</span>
|
|
3690
|
-
</div>
|
|
5500
|
+
<div class="brand"><span class="logo">T</span><span>Teams</span></div>
|
|
3691
5501
|
<div class="search">
|
|
3692
5502
|
<input
|
|
3693
5503
|
type="search"
|
|
@@ -3709,7 +5519,10 @@ var TeamsApp = class extends LitElement {
|
|
|
3709
5519
|
}}
|
|
3710
5520
|
>
|
|
3711
5521
|
<strong>${h.message.authorName}</strong>
|
|
3712
|
-
<span class="in"
|
|
5522
|
+
<span class="in"
|
|
5523
|
+
>in
|
|
5524
|
+
${s.chats.some((c) => c.id === h.channelId) ? "" : "# "}${h.channelName}</span
|
|
5525
|
+
>
|
|
3713
5526
|
<span class="snippet">${h.message.text.slice(0, 100)}</span>
|
|
3714
5527
|
</button>
|
|
3715
5528
|
</li>`
|
|
@@ -3730,15 +5543,81 @@ var TeamsApp = class extends LitElement {
|
|
|
3730
5543
|
<teams-profile-menu
|
|
3731
5544
|
.state=${s}
|
|
3732
5545
|
@teams-profile-status=${(event) => {
|
|
3733
|
-
|
|
3734
|
-
|
|
5546
|
+
const { availability, duration } = event.detail;
|
|
5547
|
+
if (isPresenceStatus(availability))
|
|
5548
|
+
this.teams.client?.setAvailability(
|
|
5549
|
+
availability,
|
|
5550
|
+
isStatusDuration(duration) ? duration : "never"
|
|
5551
|
+
);
|
|
3735
5552
|
}}
|
|
5553
|
+
@teams-profile-message=${(event) => this.teams.client?.setStatusMessage(
|
|
5554
|
+
String(event.detail.message ?? ""),
|
|
5555
|
+
isStatusDuration(event.detail.duration) ? event.detail.duration : "never"
|
|
5556
|
+
)}
|
|
5557
|
+
@teams-profile-idle=${(event) => this.teams.client?.setIdleMinutes(Number(event.detail.minutes))}
|
|
3736
5558
|
></teams-profile-menu>
|
|
3737
5559
|
</div>
|
|
3738
5560
|
</header>
|
|
3739
5561
|
`;
|
|
3740
5562
|
}
|
|
5563
|
+
dismissToast(id) {
|
|
5564
|
+
clearTimeout(this.activityToastTimers.get(id));
|
|
5565
|
+
this.activityToastTimers.delete(id);
|
|
5566
|
+
this.activityToasts = this.activityToasts.filter((t) => t.id !== id);
|
|
5567
|
+
}
|
|
5568
|
+
activityToastView(item) {
|
|
5569
|
+
return html`<div class="activity-toast" role="status" data-kind=${item.kind}>
|
|
5570
|
+
<span class="toast-text"
|
|
5571
|
+
><strong>${describeActivity(item)}</strong
|
|
5572
|
+
><span class="toast-preview">${item.preview}</span></span
|
|
5573
|
+
>
|
|
5574
|
+
<button
|
|
5575
|
+
type="button"
|
|
5576
|
+
@click=${() => {
|
|
5577
|
+
this.dismissToast(item.id);
|
|
5578
|
+
if (item.kind === "meeting") this.openMeeting(item.messageId);
|
|
5579
|
+
else void this.openActivity(item.id);
|
|
5580
|
+
}}
|
|
5581
|
+
>
|
|
5582
|
+
View
|
|
5583
|
+
</button>
|
|
5584
|
+
<button type="button" aria-label="Dismiss" @click=${() => this.dismissToast(item.id)}>
|
|
5585
|
+
${icon("close")}
|
|
5586
|
+
</button>
|
|
5587
|
+
</div>`;
|
|
5588
|
+
}
|
|
3741
5589
|
sidebar(s) {
|
|
5590
|
+
if (this.rail === "chat")
|
|
5591
|
+
return html`<office-ui-chat-sidebar
|
|
5592
|
+
.chats=${s.chats}
|
|
5593
|
+
selected-id=${s.selectedChannelId}
|
|
5594
|
+
@office-chat-select=${(e) => this.selectChannel(e.detail.id)}
|
|
5595
|
+
@office-chat-new=${() => this.newChat = true}
|
|
5596
|
+
></office-ui-chat-sidebar>`;
|
|
5597
|
+
if (this.rail === "calendar")
|
|
5598
|
+
return html`<office-ui-calendar-agenda
|
|
5599
|
+
.meetings=${s.meetings}
|
|
5600
|
+
.zone=${s.viewerZone}
|
|
5601
|
+
@office-agenda-open=${(e) => this.meetingDetails = { meetingId: e.detail.meetingId, start: e.detail.start }}
|
|
5602
|
+
@office-agenda-join=${(e) => void this.joinMeeting(e.detail.meetingId)}
|
|
5603
|
+
@office-agenda-new=${() => this.meetingForm = { meetingId: "", start: 0 }}
|
|
5604
|
+
></office-ui-calendar-agenda>
|
|
5605
|
+
<button
|
|
5606
|
+
type="button"
|
|
5607
|
+
class="show-calendar"
|
|
5608
|
+
@click=${() => this.mobileView = "conversation"}
|
|
5609
|
+
>
|
|
5610
|
+
${icon("calendar")} Open calendar
|
|
5611
|
+
</button>`;
|
|
5612
|
+
if (this.rail === "activity")
|
|
5613
|
+
return html`<office-ui-activity-feed
|
|
5614
|
+
.items=${s.activity}
|
|
5615
|
+
.filter=${this.activityFilter}
|
|
5616
|
+
@office-activity-filter=${(e) => this.activityFilter = e.detail.filter}
|
|
5617
|
+
@office-activity-open=${(e) => void this.openActivity(e.detail.id)}
|
|
5618
|
+
@office-activity-read=${(e) => this.teams.client?.markActivityRead(e.detail.id, e.detail.read)}
|
|
5619
|
+
@office-activity-read-all=${() => this.teams.client?.markAllActivityRead()}
|
|
5620
|
+
></office-ui-activity-feed>`;
|
|
3742
5621
|
if (this.rail === "calls") {
|
|
3743
5622
|
const live2 = s.channels.filter((c) => c.live);
|
|
3744
5623
|
return html`
|
|
@@ -3794,13 +5673,18 @@ var TeamsApp = class extends LitElement {
|
|
|
3794
5673
|
}
|
|
3795
5674
|
);
|
|
3796
5675
|
if (s.call && this.meeting) return this.meetingView(s);
|
|
5676
|
+
if (this.rail === "calendar") return this.calendarMain(s);
|
|
5677
|
+
if (this.rail === "chat" && !s.chats.some((c) => c.id === s.selectedChannelId))
|
|
5678
|
+
return this.chatEmpty();
|
|
3797
5679
|
return html`
|
|
3798
5680
|
${s.call && !this.meeting ? html`<div class="callbar">
|
|
3799
|
-
You are in a call in
|
|
5681
|
+
You are in a call in ${this.callHeading(s.call)}
|
|
3800
5682
|
<button
|
|
3801
5683
|
type="button"
|
|
3802
5684
|
@click=${() => {
|
|
3803
|
-
if (
|
|
5685
|
+
if (s.call.kind === "meeting") {
|
|
5686
|
+
if (this.closePreview()) [this.rail, this.meeting] = ["calendar", true];
|
|
5687
|
+
} else if (this.selectChannel(s.call.channelId)) this.meeting = true;
|
|
3804
5688
|
}}
|
|
3805
5689
|
>
|
|
3806
5690
|
Return to call
|
|
@@ -3811,43 +5695,57 @@ var TeamsApp = class extends LitElement {
|
|
|
3811
5695
|
}
|
|
3812
5696
|
conversation(s, compact = false) {
|
|
3813
5697
|
const channel = s.channel;
|
|
5698
|
+
const chat = s.chats.find((x) => x.id === s.selectedChannelId);
|
|
3814
5699
|
const c = this.teams.client;
|
|
3815
5700
|
const compose = s.editing ?? s.replyingTo;
|
|
3816
5701
|
const sharedTab = s.tabs.find((t) => t.id === this.tab);
|
|
3817
5702
|
if (sharedTab) this.retainedTab = sharedTab;
|
|
3818
5703
|
const activeTab = sharedTab ?? (this.retainedTab?.id === this.tab && this.retainedTab.channelId === s.selectedChannelId ? this.retainedTab : void 0);
|
|
3819
5704
|
return html`
|
|
3820
|
-
${compact ? nothing :
|
|
3821
|
-
|
|
3822
|
-
|
|
3823
|
-
|
|
5705
|
+
${compact ? nothing : chat ? chatHeader(chat, {
|
|
5706
|
+
back: () => this.mobileView = "list",
|
|
5707
|
+
call: () => this.startMeeting(),
|
|
5708
|
+
people: () => this.chatPeople = true
|
|
5709
|
+
}) : html`<header class="channel-head">
|
|
5710
|
+
<button
|
|
5711
|
+
type="button"
|
|
5712
|
+
class="back"
|
|
5713
|
+
aria-label="Back to channels"
|
|
5714
|
+
title="Back to channels"
|
|
5715
|
+
@click=${() => this.mobileView = "list"}
|
|
5716
|
+
>
|
|
5717
|
+
${icon("back")}
|
|
5718
|
+
</button>
|
|
5719
|
+
<h1><span class="hash">#</span> ${channel?.name ?? "No channel yet"}</h1>
|
|
5720
|
+
<nav class="tabs" role="tablist">
|
|
5721
|
+
${["posts", "files"].map(
|
|
3824
5722
|
(t) => html`<button
|
|
3825
|
-
|
|
3826
|
-
|
|
3827
|
-
|
|
3828
|
-
|
|
3829
|
-
|
|
3830
|
-
|
|
3831
|
-
|
|
5723
|
+
type="button"
|
|
5724
|
+
role="tab"
|
|
5725
|
+
aria-selected=${String(this.tab === t)}
|
|
5726
|
+
@click=${() => this.selectTab(t)}
|
|
5727
|
+
>
|
|
5728
|
+
${t === "posts" ? "Posts" : "Shared"}
|
|
5729
|
+
</button>`
|
|
3832
5730
|
)}
|
|
3833
|
-
|
|
3834
|
-
|
|
3835
|
-
|
|
3836
|
-
|
|
3837
|
-
|
|
3838
|
-
|
|
3839
|
-
|
|
3840
|
-
|
|
3841
|
-
|
|
3842
|
-
|
|
3843
|
-
|
|
3844
|
-
|
|
3845
|
-
|
|
3846
|
-
|
|
3847
|
-
|
|
3848
|
-
|
|
3849
|
-
|
|
3850
|
-
|
|
5731
|
+
${s.tabs.map((t) => html`<button type="button" role="tab" aria-selected=${String(this.tab === t.id)} @click=${() => this.selectTab(t.id)}>${t.name}</button>`)}
|
|
5732
|
+
</nav>
|
|
5733
|
+
<button
|
|
5734
|
+
type="button"
|
|
5735
|
+
aria-label="Add tab"
|
|
5736
|
+
title="Add tab"
|
|
5737
|
+
?disabled=${!channel}
|
|
5738
|
+
@click=${() => this.addingTab = !this.addingTab}
|
|
5739
|
+
>
|
|
5740
|
+
+
|
|
5741
|
+
</button>
|
|
5742
|
+
${sharedTab ? html`<button
|
|
5743
|
+
type="button"
|
|
5744
|
+
data-tab-conversation
|
|
5745
|
+
aria-label="Show tab conversation"
|
|
5746
|
+
title="Show tab conversation"
|
|
5747
|
+
aria-expanded=${String(s.thread?.root.tabId === sharedTab.id)}
|
|
5748
|
+
@click=${async () => {
|
|
3851
5749
|
if (s.thread?.root.tabId === sharedTab.id) {
|
|
3852
5750
|
await this.closeThread();
|
|
3853
5751
|
return;
|
|
@@ -3860,49 +5758,51 @@ var TeamsApp = class extends LitElement {
|
|
|
3860
5758
|
await this.updateComplete;
|
|
3861
5759
|
this.shadowRoot?.querySelector("[data-thread-heading]")?.focus();
|
|
3862
5760
|
}}
|
|
3863
|
-
|
|
3864
|
-
|
|
3865
|
-
|
|
3866
|
-
|
|
3867
|
-
|
|
3868
|
-
|
|
3869
|
-
|
|
3870
|
-
|
|
5761
|
+
>
|
|
5762
|
+
${icon("chat")}
|
|
5763
|
+
</button>` : nothing}
|
|
5764
|
+
${sharedTab?.createdBy === s.user.id ? html`<office-ui-menu-button
|
|
5765
|
+
label="Tab options"
|
|
5766
|
+
icon="more"
|
|
5767
|
+
icon-only
|
|
5768
|
+
@office-command=${(event) => {
|
|
3871
5769
|
if (event.detail.command === "rename-tab") {
|
|
3872
5770
|
const name = globalThis.prompt?.("Tab name", sharedTab.name)?.trim();
|
|
3873
5771
|
if (name) c?.renameTab(sharedTab.id, name);
|
|
3874
5772
|
} else if (event.detail.command === "remove-tab") {
|
|
3875
5773
|
if (!this.canLeaveContent()) return;
|
|
3876
|
-
if (globalThis.confirm?.(
|
|
5774
|
+
if (globalThis.confirm?.(
|
|
5775
|
+
`Remove ${sharedTab.name} from this channel?`
|
|
5776
|
+
) === true && c?.removeTab(sharedTab.id)) {
|
|
3877
5777
|
this.openRequest++;
|
|
3878
5778
|
this.preview = null;
|
|
3879
5779
|
this.tab = "posts";
|
|
3880
5780
|
}
|
|
3881
5781
|
}
|
|
3882
5782
|
}}
|
|
3883
|
-
|
|
3884
|
-
|
|
3885
|
-
|
|
3886
|
-
|
|
3887
|
-
|
|
3888
|
-
|
|
3889
|
-
|
|
3890
|
-
|
|
3891
|
-
|
|
3892
|
-
|
|
3893
|
-
|
|
3894
|
-
|
|
3895
|
-
|
|
3896
|
-
|
|
3897
|
-
|
|
3898
|
-
|
|
3899
|
-
|
|
3900
|
-
|
|
3901
|
-
|
|
3902
|
-
|
|
3903
|
-
|
|
3904
|
-
|
|
3905
|
-
|
|
5783
|
+
><office-ui-menu-item
|
|
5784
|
+
label="Rename tab"
|
|
5785
|
+
command="rename-tab"
|
|
5786
|
+
></office-ui-menu-item
|
|
5787
|
+
><office-ui-menu-item
|
|
5788
|
+
label="Remove tab"
|
|
5789
|
+
command="remove-tab"
|
|
5790
|
+
></office-ui-menu-item
|
|
5791
|
+
></office-ui-menu-button>` : nothing}
|
|
5792
|
+
<span class="topic">${channel?.topic ?? ""}</span>
|
|
5793
|
+
<div class="people" aria-label="People online">
|
|
5794
|
+
${s.people.slice(0, 5).map((p) => html`<office-ui-avatar size="sm" name=${p.name} seed=${p.id} color=${p.color} presence=${p.availability}></office-ui-avatar>`)}
|
|
5795
|
+
${s.people.length > 5 ? html`<span class="more">+${s.people.length - 5}</span>` : nothing}
|
|
5796
|
+
</div>
|
|
5797
|
+
<button
|
|
5798
|
+
type="button"
|
|
5799
|
+
class="meet"
|
|
5800
|
+
?disabled=${!channel}
|
|
5801
|
+
@click=${() => this.startMeeting()}
|
|
5802
|
+
>
|
|
5803
|
+
${s.channels.find((x) => x.id === s.selectedChannelId)?.live ? "Join call" : "Meet now"}
|
|
5804
|
+
</button>
|
|
5805
|
+
</header>`}
|
|
3906
5806
|
${c ? messageTransfers(s, c) : nothing}
|
|
3907
5807
|
${activeTab && !sharedTab && !compact ? html`<p role="status">This tab was removed from the channel. Your open copy remains here until you close it.</p>` : nothing}
|
|
3908
5808
|
${activeTab && !compact ? html`<div
|
|
@@ -3922,14 +5822,26 @@ var TeamsApp = class extends LitElement {
|
|
|
3922
5822
|
s,
|
|
3923
5823
|
c,
|
|
3924
5824
|
(attachment) => void this.openFile(attachment),
|
|
3925
|
-
() => void this.closeThread()
|
|
5825
|
+
() => void this.closeThread(),
|
|
5826
|
+
this.highlightId
|
|
3926
5827
|
) : nothing}
|
|
3927
5828
|
</div>` : this.tab === "files" && !compact ? this.fileList(s.files, s) : html`<div class="conversation-grid" data-thread=${String(!!s.thread && !compact)}>
|
|
3928
5829
|
<div class="conversation-main">
|
|
5830
|
+
${compact || s.pinned.length === 0 ? nothing : html`<teams-pinned-bar
|
|
5831
|
+
.pinned=${s.pinned}
|
|
5832
|
+
@teams-pinned-open=${(e) => void this.revealMessage(e.detail.messageId)}
|
|
5833
|
+
@teams-pinned-unpin=${(e) => c?.unpinMessage(e.detail.messageId)}
|
|
5834
|
+
></teams-pinned-bar>`}
|
|
3929
5835
|
<office-ui-chat-list
|
|
3930
5836
|
.messages=${compact ? s.messages : s.posts}
|
|
3931
5837
|
.replyCounts=${compact ? {} : s.replyCounts}
|
|
5838
|
+
.pinnedIds=${s.pinned.map((p) => p.message.id)}
|
|
3932
5839
|
self-id=${s.user.id}
|
|
5840
|
+
.highlightId=${this.highlightId}
|
|
5841
|
+
.meetings=${meetingCards(s.meetings, Date.now())}
|
|
5842
|
+
@office-chat-meeting=${(e) => e.detail.action === "join" ? void this.joinMeeting(e.detail.meetingId) : this.openMeeting(e.detail.meetingId)}
|
|
5843
|
+
@office-chat-pin=${(e) => c?.pinMessage(e.detail.messageId)}
|
|
5844
|
+
@office-chat-unpin=${(e) => c?.unpinMessage(e.detail.messageId)}
|
|
3933
5845
|
@office-chat-react=${(e) => c?.toggleReaction(e.detail.messageId, e.detail.emoji)}
|
|
3934
5846
|
@office-chat-thread=${(e) => void this.openThread(e.detail.messageId)}
|
|
3935
5847
|
@office-chat-reply=${(e) => compact ? c?.startReply(e.detail.messageId) : void this.openThread(e.detail.messageId, "reply")}
|
|
@@ -3944,9 +5856,10 @@ var TeamsApp = class extends LitElement {
|
|
|
3944
5856
|
.value=${s.draft.text}
|
|
3945
5857
|
.files=${s.draft.files}
|
|
3946
5858
|
.missingFiles=${s.draft.missingFiles}
|
|
5859
|
+
.mentionTargets=${s.mentionTargets}
|
|
3947
5860
|
@office-chat-draft=${(e) => c?.setDraft(e.detail)}
|
|
3948
5861
|
?disabled=${!channel}
|
|
3949
|
-
placeholder=${channel ? `Message # ${channel.name}` : "Create a channel first"}
|
|
5862
|
+
placeholder=${chat ? `Message ${chat.title}` : channel ? `Message # ${channel.name}` : "Create a channel first"}
|
|
3950
5863
|
@office-chat-typing=${() => c?.notifyTyping()}
|
|
3951
5864
|
@office-chat-cancel=${() => c?.cancelCompose()}
|
|
3952
5865
|
@office-chat-send=${(e) => void c?.send(e.detail)}
|
|
@@ -3957,7 +5870,8 @@ var TeamsApp = class extends LitElement {
|
|
|
3957
5870
|
s,
|
|
3958
5871
|
c,
|
|
3959
5872
|
(attachment) => void this.openFile(attachment),
|
|
3960
|
-
() => void this.closeThread()
|
|
5873
|
+
() => void this.closeThread(),
|
|
5874
|
+
this.highlightId
|
|
3961
5875
|
) : nothing}
|
|
3962
5876
|
</div>`}
|
|
3963
5877
|
`;
|
|
@@ -3969,6 +5883,42 @@ var TeamsApp = class extends LitElement {
|
|
|
3969
5883
|
this.addingTab = false;
|
|
3970
5884
|
this.creatingChannel = false;
|
|
3971
5885
|
}
|
|
5886
|
+
/** Scroll a message into view and highlight it, opening its thread when it is a reply. */
|
|
5887
|
+
async revealMessage(id) {
|
|
5888
|
+
const message = this.teams.state?.messages.find((m) => m.id === id);
|
|
5889
|
+
if (!message) return;
|
|
5890
|
+
if (message.replyTo) await this.openThread(id);
|
|
5891
|
+
await this.updateComplete;
|
|
5892
|
+
const lists = [...this.renderRoot.querySelectorAll("office-ui-chat-list")];
|
|
5893
|
+
await Promise.all(lists.map((list) => list.updateComplete));
|
|
5894
|
+
const row = lists.flatMap((list) => [
|
|
5895
|
+
...list.shadowRoot?.querySelectorAll("[data-message-id]") ?? []
|
|
5896
|
+
]).find((element) => element.dataset.messageId === id);
|
|
5897
|
+
row?.scrollIntoView({ block: "center" });
|
|
5898
|
+
row?.focus();
|
|
5899
|
+
this.highlightId = id;
|
|
5900
|
+
clearTimeout(this.highlightTimer);
|
|
5901
|
+
this.highlightTimer = setTimeout(() => this.highlightId = "", 2500);
|
|
5902
|
+
}
|
|
5903
|
+
/** Open an Activity item: its channel or thread, scrolled to the message, and mark it read. */
|
|
5904
|
+
async openActivity(id) {
|
|
5905
|
+
const c = this.teams.client;
|
|
5906
|
+
const item = c?.getState().activity.find((entry) => entry.id === id);
|
|
5907
|
+
if (!c || !item || !this.closePreview()) return;
|
|
5908
|
+
c.markActivityRead(id);
|
|
5909
|
+
this.settingsOpen = false;
|
|
5910
|
+
this.addingTab = false;
|
|
5911
|
+
this.creatingChannel = false;
|
|
5912
|
+
this.meeting = false;
|
|
5913
|
+
this.tab = "posts";
|
|
5914
|
+
this.mobileView = "conversation";
|
|
5915
|
+
c.select(item.channelId);
|
|
5916
|
+
c.search("");
|
|
5917
|
+
if (item.rootId === item.messageId) c.closeThread();
|
|
5918
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
5919
|
+
await this.updateComplete;
|
|
5920
|
+
await this.revealMessage(item.messageId);
|
|
5921
|
+
}
|
|
3972
5922
|
async openThread(id, action) {
|
|
3973
5923
|
const client = this.teams.client;
|
|
3974
5924
|
client?.openThread(id);
|
|
@@ -3978,6 +5928,166 @@ var TeamsApp = class extends LitElement {
|
|
|
3978
5928
|
await this.updateComplete;
|
|
3979
5929
|
this.shadowRoot?.querySelector("[data-thread-heading]")?.focus();
|
|
3980
5930
|
}
|
|
5931
|
+
callHeading(call) {
|
|
5932
|
+
return call.kind === "channel" ? `# ${call.channelName}` : call.channelName;
|
|
5933
|
+
}
|
|
5934
|
+
/** Teams rail: if a chat is selected, go back to the channel you were in. */
|
|
5935
|
+
leaveChatSelection() {
|
|
5936
|
+
const st = this.teams.state;
|
|
5937
|
+
const c = this.teams.client;
|
|
5938
|
+
if (!st || !c || !st.chats.some((x) => x.id === st.selectedChannelId)) return;
|
|
5939
|
+
const target = st.channels.some((x) => x.id === this.lastChannelId) ? this.lastChannelId : st.channels[0]?.id;
|
|
5940
|
+
if (target) c.select(target);
|
|
5941
|
+
}
|
|
5942
|
+
chatEmpty() {
|
|
5943
|
+
return html`<div class="empty-main">
|
|
5944
|
+
<h1>Chat</h1>
|
|
5945
|
+
<p>Pick a chat from the list, or start a new one.</p>
|
|
5946
|
+
<button type="button" @click=${() => this.newChat = true}>New chat</button>
|
|
5947
|
+
</div>`;
|
|
5948
|
+
}
|
|
5949
|
+
commitChat(ids, name) {
|
|
5950
|
+
const c = this.client;
|
|
5951
|
+
if (!c || !this.closePreview()) return false;
|
|
5952
|
+
const id = c.createGroupChat(ids, name);
|
|
5953
|
+
if (!id) return false;
|
|
5954
|
+
this.newChat = false;
|
|
5955
|
+
this.rail = "chat";
|
|
5956
|
+
this.meeting = false;
|
|
5957
|
+
this.tab = "posts";
|
|
5958
|
+
this.mobileView = "conversation";
|
|
5959
|
+
return true;
|
|
5960
|
+
}
|
|
5961
|
+
chatDialogs(s) {
|
|
5962
|
+
const c = this.teams.client;
|
|
5963
|
+
const chat = s.chats.find((x) => x.id === s.selectedChannelId) ?? null;
|
|
5964
|
+
return html`
|
|
5965
|
+
<teams-new-chat-dialog
|
|
5966
|
+
?open=${this.newChat}
|
|
5967
|
+
.contacts=${s.contacts}
|
|
5968
|
+
.create=${(ids, name) => this.commitChat(ids, name)}
|
|
5969
|
+
@teams-dialog-close=${() => this.newChat = false}
|
|
5970
|
+
></teams-new-chat-dialog>
|
|
5971
|
+
<teams-chat-people-dialog
|
|
5972
|
+
?open=${this.chatPeople && chat !== null}
|
|
5973
|
+
.chat=${chat}
|
|
5974
|
+
.contacts=${s.contacts}
|
|
5975
|
+
@teams-chat-rename=${(e) => c?.renameChat(e.detail.id, e.detail.name)}
|
|
5976
|
+
@teams-chat-add=${(e) => c?.addToChat(e.detail.id, e.detail.userIds)}
|
|
5977
|
+
@teams-chat-remove=${(e) => c?.removeFromChat(e.detail.id, e.detail.userId)}
|
|
5978
|
+
@teams-chat-leave=${(e) => {
|
|
5979
|
+
if (globalThis.confirm?.("Leave this chat? You will stop receiving its messages.") === false)
|
|
5980
|
+
return;
|
|
5981
|
+
if (c?.leaveChat(e.detail.id)) {
|
|
5982
|
+
this.chatPeople = false;
|
|
5983
|
+
this.mobileView = "list";
|
|
5984
|
+
}
|
|
5985
|
+
}}
|
|
5986
|
+
@teams-dialog-close=${() => this.chatPeople = false}
|
|
5987
|
+
></teams-chat-people-dialog>
|
|
5988
|
+
`;
|
|
5989
|
+
}
|
|
5990
|
+
// ---- calendar ---------------------------------------------------------------------------
|
|
5991
|
+
calendarMain(s) {
|
|
5992
|
+
return html`
|
|
5993
|
+
<div class="calendar-back">
|
|
5994
|
+
<button type="button" @click=${() => this.mobileView = "list"}>
|
|
5995
|
+
${icon("back")} Upcoming meetings
|
|
5996
|
+
</button>
|
|
5997
|
+
</div>
|
|
5998
|
+
<office-ui-calendar-view
|
|
5999
|
+
.meetings=${s.meetings}
|
|
6000
|
+
.zone=${s.viewerZone}
|
|
6001
|
+
@office-calendar-open=${(e) => this.meetingDetails = { meetingId: e.detail.meetingId, start: e.detail.start }}
|
|
6002
|
+
@office-calendar-new=${(e) => this.meetingForm = { meetingId: "", start: e.detail.start }}
|
|
6003
|
+
></office-ui-calendar-view>
|
|
6004
|
+
`;
|
|
6005
|
+
}
|
|
6006
|
+
/** Open the calendar on a meeting's details, for example from its reminder. */
|
|
6007
|
+
openMeeting(meetingId, start = 0) {
|
|
6008
|
+
if (!this.closePreview()) return;
|
|
6009
|
+
this.settingsOpen = false;
|
|
6010
|
+
this.meeting = false;
|
|
6011
|
+
this.rail = "calendar";
|
|
6012
|
+
this.mobileView = "conversation";
|
|
6013
|
+
this.meetingDetails = { meetingId, start };
|
|
6014
|
+
}
|
|
6015
|
+
async joinMeeting(meetingId) {
|
|
6016
|
+
if (!this.closePreview()) return;
|
|
6017
|
+
this.meetingDetails = null;
|
|
6018
|
+
this.settingsOpen = false;
|
|
6019
|
+
if (await this.teams.client?.joinMeeting(meetingId)) {
|
|
6020
|
+
this.meeting = true;
|
|
6021
|
+
this.rail = "calendar";
|
|
6022
|
+
this.mobileView = "conversation";
|
|
6023
|
+
}
|
|
6024
|
+
}
|
|
6025
|
+
saveMeeting(form, id, occurrence) {
|
|
6026
|
+
const c = this.client;
|
|
6027
|
+
if (!c) return false;
|
|
6028
|
+
const saved = id && occurrence ? c.editOccurrence(id, occurrence, {
|
|
6029
|
+
start: form.start,
|
|
6030
|
+
end: form.end,
|
|
6031
|
+
title: form.title,
|
|
6032
|
+
...form.description !== void 0 ? { description: form.description } : {}
|
|
6033
|
+
}) : id ? c.updateMeeting(id, form) : c.createMeeting(form);
|
|
6034
|
+
if (!saved) return false;
|
|
6035
|
+
this.meetingForm = null;
|
|
6036
|
+
return true;
|
|
6037
|
+
}
|
|
6038
|
+
calendarDialogs(s) {
|
|
6039
|
+
const c = this.teams.client;
|
|
6040
|
+
const editing = this.meetingForm?.meetingId ? s.meetings.find((m) => m.id === this.meetingForm?.meetingId) ?? null : null;
|
|
6041
|
+
const details = this.meetingDetails ? s.meetings.find((m) => m.id === this.meetingDetails?.meetingId) ?? null : null;
|
|
6042
|
+
return html`
|
|
6043
|
+
<teams-meeting-dialog
|
|
6044
|
+
?open=${this.meetingForm !== null}
|
|
6045
|
+
.meeting=${editing}
|
|
6046
|
+
.start=${this.meetingForm?.start ?? 0}
|
|
6047
|
+
.occurrence=${this.meetingForm?.occurrence ?? 0}
|
|
6048
|
+
.contacts=${s.contacts}
|
|
6049
|
+
.channels=${s.channels.map((ch) => ({ id: ch.id, name: ch.name }))}
|
|
6050
|
+
.save=${(form, id, occurrence) => this.saveMeeting(form, id, occurrence)}
|
|
6051
|
+
@teams-dialog-close=${() => this.meetingForm = null}
|
|
6052
|
+
></teams-meeting-dialog>
|
|
6053
|
+
<teams-meeting-details
|
|
6054
|
+
?open=${details !== null}
|
|
6055
|
+
.meeting=${details}
|
|
6056
|
+
.occurrenceStart=${this.meetingDetails?.start ?? 0}
|
|
6057
|
+
.zone=${s.viewerZone}
|
|
6058
|
+
.channelName=${s.channels.find((ch) => ch.id === details?.channelId)?.name ?? ""}
|
|
6059
|
+
@teams-meeting-join=${(e) => void this.joinMeeting(e.detail.meetingId)}
|
|
6060
|
+
@teams-meeting-chat=${(e) => {
|
|
6061
|
+
const target = s.meetings.find((m) => m.id === e.detail.meetingId);
|
|
6062
|
+
const conversation = target?.chatId ?? target?.channelId;
|
|
6063
|
+
this.meetingDetails = null;
|
|
6064
|
+
if (conversation) this.selectChannel(conversation);
|
|
6065
|
+
}}
|
|
6066
|
+
@teams-meeting-edit=${(e) => {
|
|
6067
|
+
const { meetingId, scope, recurrenceId } = e.detail;
|
|
6068
|
+
const shown = this.meetingDetails?.start ?? 0;
|
|
6069
|
+
this.meetingDetails = null;
|
|
6070
|
+
this.meetingForm = scope === "occurrence" ? { meetingId, start: shown, occurrence: recurrenceId } : { meetingId, start: 0 };
|
|
6071
|
+
}}
|
|
6072
|
+
@teams-meeting-cancel=${(e) => {
|
|
6073
|
+
const { meetingId, scope, recurrenceId } = e.detail;
|
|
6074
|
+
if (scope === "occurrence") {
|
|
6075
|
+
if (c?.cancelOccurrence(meetingId, recurrenceId)) this.meetingDetails = null;
|
|
6076
|
+
return;
|
|
6077
|
+
}
|
|
6078
|
+
const ask = details?.repeat === "none" ? "Cancel this meeting for everyone?" : "Cancel every event in this series?";
|
|
6079
|
+
if (globalThis.confirm?.(ask) === false) return;
|
|
6080
|
+
if (c?.cancelMeeting(meetingId)) this.meetingDetails = null;
|
|
6081
|
+
}}
|
|
6082
|
+
@teams-meeting-ics=${(e) => {
|
|
6083
|
+
const file = c?.meetingIcs(e.detail.meetingId);
|
|
6084
|
+
if (file && !downloadText(file.name, file.text))
|
|
6085
|
+
this.notify("Could not start the download");
|
|
6086
|
+
}}
|
|
6087
|
+
@teams-dialog-close=${() => this.meetingDetails = null}
|
|
6088
|
+
></teams-meeting-details>
|
|
6089
|
+
`;
|
|
6090
|
+
}
|
|
3981
6091
|
async resumeDraft(context) {
|
|
3982
6092
|
if (!this.closePreview() || !this.teams.client?.openDraft(context)) return;
|
|
3983
6093
|
this.rail = "teams";
|
|
@@ -4046,7 +6156,7 @@ var TeamsApp = class extends LitElement {
|
|
|
4046
6156
|
if (call.phase === "prejoin")
|
|
4047
6157
|
return html`
|
|
4048
6158
|
<office-ui-prejoin
|
|
4049
|
-
heading=${
|
|
6159
|
+
heading=${this.callHeading(call)}
|
|
4050
6160
|
name=${s.user.name}
|
|
4051
6161
|
.preview=${call.preview}
|
|
4052
6162
|
?audio=${call.prejoin.audio}
|
|
@@ -4060,7 +6170,7 @@ var TeamsApp = class extends LitElement {
|
|
|
4060
6170
|
return html`
|
|
4061
6171
|
<section class="meeting">
|
|
4062
6172
|
<office-ui-call-controls
|
|
4063
|
-
heading=${
|
|
6173
|
+
heading=${this.callHeading(call)}
|
|
4064
6174
|
started-at=${call.startedAt ?? 0}
|
|
4065
6175
|
?mic=${self?.state.audio}
|
|
4066
6176
|
?camera=${self?.state.video}
|
|
@@ -4145,22 +6255,32 @@ function createTeams(options) {
|
|
|
4145
6255
|
var TEAMS_TAGS = [
|
|
4146
6256
|
"office-ui-avatar",
|
|
4147
6257
|
"office-ui-app-rail",
|
|
6258
|
+
"office-ui-activity-feed",
|
|
4148
6259
|
"office-ui-channel-list",
|
|
4149
6260
|
"office-ui-chat-list",
|
|
4150
6261
|
"office-ui-chat-composer",
|
|
4151
6262
|
"office-ui-prejoin",
|
|
4152
6263
|
"office-ui-call-grid",
|
|
4153
|
-
"office-ui-call-controls"
|
|
6264
|
+
"office-ui-call-controls",
|
|
6265
|
+
"office-ui-chat-sidebar",
|
|
6266
|
+
"office-ui-people-picker",
|
|
6267
|
+
"office-ui-calendar-view",
|
|
6268
|
+
"office-ui-calendar-agenda"
|
|
4154
6269
|
];
|
|
4155
6270
|
function registerTeams() {
|
|
4156
6271
|
defineAvatar();
|
|
4157
6272
|
defineAppRail();
|
|
6273
|
+
defineActivityFeed();
|
|
4158
6274
|
defineChannelList();
|
|
4159
6275
|
defineChatList();
|
|
4160
6276
|
defineChatComposer();
|
|
4161
6277
|
definePrejoin();
|
|
4162
6278
|
defineCallGrid();
|
|
4163
6279
|
defineCallControls();
|
|
6280
|
+
defineChatSidebar();
|
|
6281
|
+
definePeoplePicker();
|
|
6282
|
+
defineCalendarView();
|
|
6283
|
+
defineCalendarAgenda();
|
|
4164
6284
|
}
|
|
4165
6285
|
|
|
4166
|
-
export { EMOJI, OfficeUiAppRail, OfficeUiAvatar, OfficeUiCallControls, OfficeUiCallGrid, OfficeUiChannelList, OfficeUiChatComposer, OfficeUiChatList, OfficeUiPrejoin, QUICK_REACTIONS, TEAMS_TAGS, TeamsApp, TeamsChannelTab, TeamsContentPreview, TeamsController, TeamsElement, TeamsFilesPanel, TeamsSettings, XLSX_EDITOR_EVENTS, announceFileCommand, applyTeamsProps, blobFor, colorFor, createTeams, dayLabel, defineAppRail, defineAvatar, defineCallControls, defineCallGrid, defineChannelList, defineChatComposer, defineChatList, definePrejoin, defineTeamsApp, defineTeamsChannelTab, defineTeamsContentPreview, defineTeamsFilesPanel, defineTeamsSettings, downloadBytes, emit, emitEvent, formatElapsed, formatSize, formatTime, icon, listenTeamsEvents, loadConfig, loadIdentity, parseIceLines, pickFile, registerTeams, safeStorage, saveConfig, saveExtension, saveIdentity, withExtension, withStyles };
|
|
6286
|
+
export { EMOJI, OfficeUiActivityFeed, OfficeUiAppRail, OfficeUiAvatar, OfficeUiCalendarAgenda, OfficeUiCalendarView, OfficeUiCallControls, OfficeUiCallGrid, OfficeUiChannelList, OfficeUiChatComposer, OfficeUiChatList, OfficeUiChatSidebar, OfficeUiPeoplePicker, OfficeUiPrejoin, QUICK_REACTIONS, TEAMS_TAGS, TeamsApp, TeamsChannelTab, TeamsContentPreview, TeamsController, TeamsElement, TeamsFilesPanel, TeamsSettings, XLSX_EDITOR_EVENTS, activityTime, announceFileCommand, applyTeamsProps, blobFor, colorFor, createTeams, dayLabel, defineActivityFeed, defineAppRail, defineAvatar, defineCalendarAgenda, defineCalendarView, defineCallControls, defineCallGrid, defineChannelList, defineChatComposer, defineChatList, defineChatSidebar, definePeoplePicker, definePrejoin, defineTeamsApp, defineTeamsChannelTab, defineTeamsContentPreview, defineTeamsFilesPanel, defineTeamsSettings, downloadBytes, emit, emitEvent, formatElapsed, formatSize, formatTime, formatWhen, icon, listenTeamsEvents, loadConfig, loadIdentity, parseIceLines, pickFile, registerTeams, safeStorage, saveConfig, saveExtension, saveIdentity, withExtension, withStyles };
|