ooxml-ui 1.13.0 → 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 +379 -4
- package/dist/{chunk-D7JPVAYS.js → chunk-C3MXKNNK.js} +2139 -136
- package/dist/{chunk-EL2A3BDM.js → chunk-C5F7454A.js} +2 -2
- package/dist/{chunk-3XST4F6J.js → chunk-DSQBXLMO.js} +1 -1
- package/dist/{chunk-BFPHRWEB.js → chunk-LAVVSCRJ.js} +85 -44
- package/dist/controls.js +1 -1
- package/dist/dialog/options-dialog.d.ts +41 -0
- package/dist/dialog/options-dialog.d.ts.map +1 -1
- 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.d.ts +118 -0
- package/dist/docx/locales/objects.d.ts +37 -0
- package/dist/docx/locales/shapes.d.ts +101 -0
- package/dist/docx/localization-strings.d.ts +118 -0
- package/dist/docx/note-editor.d.ts +7 -1
- 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 +2 -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 +6 -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/table-model-adapter.d.ts +1 -1
- package/dist/docx/table-navigation.d.ts +8 -0
- package/dist/docx.js +3046 -376
- package/dist/index.d.ts +1 -1
- package/dist/index.js +4 -4
- 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-J3GEBMYK.cjs → chunk-4NBVWV6I.cjs} +83 -0
- package/dist/pptx/{chunk-J4HVGXPW.cjs → chunk-5DUBDWOU.cjs} +4544 -2587
- 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-DZUSNYRA.mjs → chunk-GUAP5VUN.mjs} +3775 -1854
- package/dist/pptx/{chunk-K3S2A64B.cjs → chunk-HULZNSHL.cjs} +13 -13
- package/dist/pptx/{chunk-CB2DZVKL.mjs → chunk-OJXPN2WX.mjs} +83 -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.d.ts.map +1 -1
- package/dist/pptx/index.cjs +3235 -3099
- 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/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.d.ts +34 -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 +1 -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/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/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/teams/activity-feed.d.ts +36 -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/settings-notifications.d.ts +9 -0
- package/dist/teams/app/store.d.ts +1 -1
- package/dist/teams/app/teams-app.d.ts +65 -3
- 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 +15 -3
- 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 +32 -2
- 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 +2 -2
- 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.js +2110 -150
- 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/tabs/contextual.d.ts +4 -0
- package/dist/xlsx.js +2718 -359
- 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
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { THEME_CSS, installOfficeUiTheme } from './chunk-7E3HU7RL.js';
|
|
2
|
-
import { defineMenuButton, defineMenuItem, registerControls, defineSwitch } from './chunk-
|
|
2
|
+
import { defineMenuButton, defineMenuItem, registerControls, defineSwitch } from './chunk-LAVVSCRJ.js';
|
|
3
3
|
import { registerIcon, getIcon } from './chunk-M6GF5ED2.js';
|
|
4
4
|
import { initialsOf, definePresence } from './chunk-KNC2UEUR.js';
|
|
5
5
|
import { definer, OfficeElement, controlStyles } from './chunk-CWBSXK7P.js';
|
|
6
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, 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, 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,6 +42,17 @@ 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",
|
|
47
58
|
pin: "M7 3h6l-1 5 3 3H5l3-3ZM10 11v6",
|
|
@@ -62,7 +73,9 @@ var GLYPHS = {
|
|
|
62
73
|
screenShare: "M3 4h14v9H3ZM7 17h6M10 13v4M10 10V6M8 8l2-2 2 2",
|
|
63
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",
|
|
64
75
|
phoneOff: "M3 11c4-3 10-3 14 0l-1.5 2.5-3-1V10a9 9 0 0 0-5 0v2.5l-3 1Z",
|
|
65
|
-
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"
|
|
66
79
|
};
|
|
67
80
|
for (const [name, d] of Object.entries(GLYPHS)) registerIcon(name, d);
|
|
68
81
|
function icon(name) {
|
|
@@ -73,54 +86,232 @@ function icon(name) {
|
|
|
73
86
|
</svg>`;
|
|
74
87
|
}
|
|
75
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
|
+
|
|
76
211
|
// raw-css:/home/runner/work/ooxml/ooxml/src/ui/src/teams/app-rail.css?raw
|
|
77
|
-
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";
|
|
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";
|
|
78
213
|
|
|
79
214
|
// src/teams/app-rail.ts
|
|
215
|
+
var total = (n) => n > 99 ? "99+" : String(n);
|
|
80
216
|
var OfficeUiAppRail = class extends TeamsElement {
|
|
81
217
|
static styles = withStyles(app_rail_default);
|
|
82
218
|
static properties = {
|
|
83
219
|
items: { attribute: false },
|
|
84
220
|
selected: { type: String },
|
|
85
|
-
hideLabels: { type: Boolean, attribute: "hide-labels", reflect: true }
|
|
221
|
+
hideLabels: { type: Boolean, attribute: "hide-labels", reflect: true },
|
|
222
|
+
moreOpen: { state: true }
|
|
86
223
|
};
|
|
87
224
|
constructor() {
|
|
88
225
|
super();
|
|
89
226
|
this.items = [];
|
|
90
227
|
this.selected = "";
|
|
91
228
|
this.hideLabels = false;
|
|
229
|
+
this.moreOpen = false;
|
|
92
230
|
}
|
|
93
231
|
connectedCallback() {
|
|
94
232
|
super.connectedCallback();
|
|
95
233
|
this.setAttribute("role", "navigation");
|
|
96
234
|
this.setAttribute("aria-label", "App bar");
|
|
97
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
|
+
}
|
|
98
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);
|
|
99
256
|
return html`
|
|
100
257
|
<ul>
|
|
101
258
|
${this.items.map(
|
|
102
259
|
(item) => html`
|
|
103
|
-
<li>
|
|
104
|
-
<button
|
|
105
|
-
type="button"
|
|
106
|
-
aria-label=${item.label}
|
|
107
|
-
title=${item.label}
|
|
108
|
-
aria-current=${this.selected === item.id ? "page" : "false"}
|
|
109
|
-
@click=${() => this.fire("office-rail-select", { id: item.id })}
|
|
110
|
-
>
|
|
111
|
-
<span class="glyph">
|
|
112
|
-
${icon(item.icon)}
|
|
113
|
-
${item.badge ? html`<span class="badge">${item.badge > 99 ? "99+" : item.badge}</span>` : ""}
|
|
114
|
-
</span>
|
|
115
|
-
<span class=${item.shortLabel ? "label has-short" : "label"}>${item.label}</span>
|
|
116
|
-
${item.shortLabel ? html`<span class="short" aria-hidden="true">${item.shortLabel}</span>` : nothing}
|
|
117
|
-
</button>
|
|
118
|
-
</li>
|
|
260
|
+
<li data-secondary=${String(item.secondary === true)}>${this.button(item)}</li>
|
|
119
261
|
`
|
|
120
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}
|
|
121
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}
|
|
122
297
|
`;
|
|
123
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
|
+
}
|
|
124
315
|
};
|
|
125
316
|
var defineAppRail = definer("office-ui-app-rail", () => OfficeUiAppRail);
|
|
126
317
|
|
|
@@ -179,10 +370,10 @@ var call_controls_default = ":host {\n display: flex;\n align-items: center;\n j
|
|
|
179
370
|
|
|
180
371
|
// src/teams/call-controls.ts
|
|
181
372
|
var formatElapsed = (ms) => {
|
|
182
|
-
const
|
|
373
|
+
const total2 = Math.max(0, Math.floor(ms / 1e3));
|
|
183
374
|
const pad = (n) => String(n).padStart(2, "0");
|
|
184
|
-
const h = Math.floor(
|
|
185
|
-
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)}`;
|
|
186
377
|
};
|
|
187
378
|
var OfficeUiCallControls = class extends TeamsElement {
|
|
188
379
|
static styles = withStyles(call_controls_default);
|
|
@@ -266,6 +457,346 @@ var OfficeUiCallControls = class extends TeamsElement {
|
|
|
266
457
|
};
|
|
267
458
|
var defineCallControls = definer("office-ui-call-controls", () => OfficeUiCallControls);
|
|
268
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
|
+
|
|
269
800
|
// raw-css:/home/runner/work/ooxml/ooxml/src/ui/src/teams/call-grid.css?raw
|
|
270
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";
|
|
271
802
|
|
|
@@ -399,7 +930,7 @@ var OfficeUiChannelList = class extends TeamsElement {
|
|
|
399
930
|
var defineChannelList = definer("office-ui-channel-list", () => OfficeUiChannelList);
|
|
400
931
|
|
|
401
932
|
// raw-css:/home/runner/work/ooxml/ooxml/src/ui/src/teams/chat-composer.css?raw
|
|
402
|
-
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";
|
|
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";
|
|
403
934
|
var EMOJI = [
|
|
404
935
|
"\u{1F600}",
|
|
405
936
|
"\u{1F604}",
|
|
@@ -434,8 +965,12 @@ var OfficeUiChatComposer = class extends TeamsElement {
|
|
|
434
965
|
value: { type: String },
|
|
435
966
|
files: { state: true },
|
|
436
967
|
missingFiles: { attribute: false },
|
|
437
|
-
emojiOpen: { state: true }
|
|
968
|
+
emojiOpen: { state: true },
|
|
969
|
+
mentionTargets: { attribute: false },
|
|
970
|
+
picker: { state: true },
|
|
971
|
+
pickerIndex: { state: true }
|
|
438
972
|
};
|
|
973
|
+
inserted = [];
|
|
439
974
|
lastTyping = 0;
|
|
440
975
|
constructor() {
|
|
441
976
|
super();
|
|
@@ -448,6 +983,9 @@ var OfficeUiChatComposer = class extends TeamsElement {
|
|
|
448
983
|
this.files = [];
|
|
449
984
|
this.missingFiles = [];
|
|
450
985
|
this.emojiOpen = false;
|
|
986
|
+
this.mentionTargets = [];
|
|
987
|
+
this.picker = null;
|
|
988
|
+
this.pickerIndex = 0;
|
|
451
989
|
}
|
|
452
990
|
focusMessage() {
|
|
453
991
|
void this.updateComplete.then(
|
|
@@ -472,15 +1010,19 @@ var OfficeUiChatComposer = class extends TeamsElement {
|
|
|
472
1010
|
}
|
|
473
1011
|
submit() {
|
|
474
1012
|
if (!this.canSend) return;
|
|
475
|
-
const { value: text, files } = this;
|
|
1013
|
+
const { value: text, files, inserted: mentions } = this;
|
|
476
1014
|
this.value = "";
|
|
477
1015
|
this.files = [];
|
|
1016
|
+
this.inserted = [];
|
|
478
1017
|
this.emojiOpen = false;
|
|
479
|
-
this.
|
|
1018
|
+
this.picker = null;
|
|
1019
|
+
const detail = { text, files, ...mentions.length ? { mentions } : {} };
|
|
1020
|
+
this.fire("office-chat-send", detail);
|
|
480
1021
|
this.focusMessage();
|
|
481
1022
|
}
|
|
482
1023
|
onInput(event) {
|
|
483
1024
|
this.value = event.target.value;
|
|
1025
|
+
this.syncPicker();
|
|
484
1026
|
this.saveDraft();
|
|
485
1027
|
const now = Date.now();
|
|
486
1028
|
if (now - this.lastTyping > 2e3) {
|
|
@@ -488,7 +1030,51 @@ var OfficeUiChatComposer = class extends TeamsElement {
|
|
|
488
1030
|
this.fire("office-chat-typing", {});
|
|
489
1031
|
}
|
|
490
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
|
+
}
|
|
491
1076
|
onKeydown(event) {
|
|
1077
|
+
if (this.pickerKey(event)) return;
|
|
492
1078
|
if (event.key === "Escape" && this.emojiOpen) {
|
|
493
1079
|
this.emojiOpen = false;
|
|
494
1080
|
this.focusMessage();
|
|
@@ -527,6 +1113,34 @@ var OfficeUiChatComposer = class extends TeamsElement {
|
|
|
527
1113
|
if (n.length === 0) return "";
|
|
528
1114
|
return n.length === 1 ? `${n[0]} is typing\u2026` : `${n.join(", ")} are typing\u2026`;
|
|
529
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
|
+
}
|
|
530
1144
|
render() {
|
|
531
1145
|
const banner = this.editing ? "Editing message" : this.replyingTo !== null ? `Replying to ${this.replyingTo}` : "";
|
|
532
1146
|
return html`
|
|
@@ -576,9 +1190,13 @@ var OfficeUiChatComposer = class extends TeamsElement {
|
|
|
576
1190
|
${icon("close")}
|
|
577
1191
|
</button>
|
|
578
1192
|
</div>` : nothing}
|
|
1193
|
+
${this.mentionList()}
|
|
579
1194
|
<textarea
|
|
580
1195
|
rows="1"
|
|
581
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}
|
|
582
1200
|
.value=${live(this.value)}
|
|
583
1201
|
placeholder=${this.placeholder}
|
|
584
1202
|
?disabled=${this.disabled}
|
|
@@ -590,6 +1208,11 @@ var OfficeUiChatComposer = class extends TeamsElement {
|
|
|
590
1208
|
}
|
|
591
1209
|
}}
|
|
592
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}
|
|
593
1216
|
></textarea>
|
|
594
1217
|
${this.files.length ? html`<ul class="pending">
|
|
595
1218
|
${this.files.map(
|
|
@@ -672,7 +1295,7 @@ var OfficeUiChatComposer = class extends TeamsElement {
|
|
|
672
1295
|
var defineChatComposer = definer("office-ui-chat-composer", () => OfficeUiChatComposer);
|
|
673
1296
|
|
|
674
1297
|
// raw-css:/home/runner/work/ooxml/ooxml/src/ui/src/teams/chat-list.css?raw
|
|
675
|
-
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";
|
|
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";
|
|
676
1299
|
|
|
677
1300
|
// src/teams/chat-list.ts
|
|
678
1301
|
var QUICK_REACTIONS = ["\u{1F44D}", "\u2764\uFE0F", "\u{1F602}", "\u{1F62E}", "\u{1F622}", "\u{1F389}"];
|
|
@@ -690,7 +1313,9 @@ var OfficeUiChatList = class extends TeamsElement {
|
|
|
690
1313
|
messages: { attribute: false },
|
|
691
1314
|
selfId: { type: String, attribute: "self-id" },
|
|
692
1315
|
replyCounts: { attribute: false },
|
|
693
|
-
pinnedIds: { attribute: false }
|
|
1316
|
+
pinnedIds: { attribute: false },
|
|
1317
|
+
highlightId: { type: String, attribute: "highlight-id" },
|
|
1318
|
+
meetings: { attribute: false }
|
|
694
1319
|
};
|
|
695
1320
|
stickToBottom = true;
|
|
696
1321
|
constructor() {
|
|
@@ -699,6 +1324,8 @@ var OfficeUiChatList = class extends TeamsElement {
|
|
|
699
1324
|
this.selfId = "";
|
|
700
1325
|
this.replyCounts = {};
|
|
701
1326
|
this.pinnedIds = [];
|
|
1327
|
+
this.highlightId = "";
|
|
1328
|
+
this.meetings = {};
|
|
702
1329
|
}
|
|
703
1330
|
connectedCallback() {
|
|
704
1331
|
super.connectedCallback();
|
|
@@ -718,6 +1345,11 @@ var OfficeUiChatList = class extends TeamsElement {
|
|
|
718
1345
|
const rows = [];
|
|
719
1346
|
let previous;
|
|
720
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
|
+
}
|
|
721
1353
|
if (!previous || dayLabel(previous.ts) !== dayLabel(m.ts))
|
|
722
1354
|
rows.push(html`<div class="day"><span>${dayLabel(m.ts)}</span></div>`);
|
|
723
1355
|
const grouped = previous !== void 0 && previous.authorId === m.authorId && m.ts - previous.ts < GROUP_MS && !m.replyTo && dayLabel(previous.ts) === dayLabel(m.ts);
|
|
@@ -735,7 +1367,9 @@ var OfficeUiChatList = class extends TeamsElement {
|
|
|
735
1367
|
tabindex="-1"
|
|
736
1368
|
data-message-id=${m.id}
|
|
737
1369
|
data-own=${String(own)}
|
|
1370
|
+
data-highlight=${String(m.id === this.highlightId)}
|
|
738
1371
|
data-grouped=${String(grouped)}
|
|
1372
|
+
data-mentions-you=${String(!m.deleted && mentionsUser(m, this.selfId) && !own)}
|
|
739
1373
|
>
|
|
740
1374
|
<div class="gutter">
|
|
741
1375
|
${grouped ? nothing : html`<office-ui-avatar name=${m.authorName} seed=${m.authorId}></office-ui-avatar>`}
|
|
@@ -751,7 +1385,8 @@ var OfficeUiChatList = class extends TeamsElement {
|
|
|
751
1385
|
<strong>${parent.authorName}</strong
|
|
752
1386
|
>${parent.deleted ? "This message was deleted" : parent.text.slice(0, 120)}
|
|
753
1387
|
</blockquote>` : nothing}
|
|
754
|
-
${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}
|
|
755
1390
|
${!m.deleted && m.attachments?.length ? this.files(m.attachments) : nothing}
|
|
756
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}
|
|
757
1392
|
</div>
|
|
@@ -776,6 +1411,47 @@ var OfficeUiChatList = class extends TeamsElement {
|
|
|
776
1411
|
</article>
|
|
777
1412
|
`;
|
|
778
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
|
+
}
|
|
779
1455
|
toolbar(m, own) {
|
|
780
1456
|
return html`
|
|
781
1457
|
<div class="toolbar" role="toolbar" aria-label="Message actions">
|
|
@@ -855,6 +1531,161 @@ var OfficeUiChatList = class extends TeamsElement {
|
|
|
855
1531
|
};
|
|
856
1532
|
var defineChatList = definer("office-ui-chat-list", () => OfficeUiChatList);
|
|
857
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
|
+
|
|
858
1689
|
// raw-css:/home/runner/work/ooxml/ooxml/src/ui/src/teams/prejoin.css?raw
|
|
859
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";
|
|
860
1691
|
|
|
@@ -937,13 +1768,15 @@ var OfficeUiPrejoin = class extends TeamsElement {
|
|
|
937
1768
|
};
|
|
938
1769
|
var definePrejoin = definer("office-ui-prejoin", () => OfficeUiPrejoin);
|
|
939
1770
|
var TeamsController = class {
|
|
940
|
-
constructor(host, onNotice) {
|
|
1771
|
+
constructor(host, onNotice, onNotification = () => void 0) {
|
|
941
1772
|
this.host = host;
|
|
942
1773
|
this.onNotice = onNotice;
|
|
1774
|
+
this.onNotification = onNotification;
|
|
943
1775
|
host.addController(this);
|
|
944
1776
|
}
|
|
945
1777
|
host;
|
|
946
1778
|
onNotice;
|
|
1779
|
+
onNotification;
|
|
947
1780
|
client = null;
|
|
948
1781
|
state = null;
|
|
949
1782
|
off = [];
|
|
@@ -958,7 +1791,8 @@ var TeamsController = class {
|
|
|
958
1791
|
this.state = client.getState();
|
|
959
1792
|
this.host.requestUpdate();
|
|
960
1793
|
}),
|
|
961
|
-
client.on("notice", this.onNotice)
|
|
1794
|
+
client.on("notice", this.onNotice),
|
|
1795
|
+
client.on("notification", this.onNotification)
|
|
962
1796
|
];
|
|
963
1797
|
this.host.requestUpdate();
|
|
964
1798
|
}
|
|
@@ -1954,7 +2788,7 @@ function defineTeamsFilesPanel() {
|
|
|
1954
2788
|
}
|
|
1955
2789
|
|
|
1956
2790
|
// raw-css:/home/runner/work/ooxml/ooxml/src/ui/src/teams/app/teams-settings.css?raw
|
|
1957
|
-
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";
|
|
1958
2792
|
|
|
1959
2793
|
// raw-css:/home/runner/work/ooxml/ooxml/src/ui/src/teams/app/settings-previews.css?raw
|
|
1960
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";
|
|
@@ -2023,6 +2857,53 @@ function densityChoices(density, change) {
|
|
|
2023
2857
|
)}
|
|
2024
2858
|
</fieldset>`;
|
|
2025
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
|
+
}
|
|
2026
2907
|
var SETTINGS_CATEGORIES = [
|
|
2027
2908
|
["general", "General"],
|
|
2028
2909
|
["appearance", "Appearance and accessibility"],
|
|
@@ -2047,6 +2928,21 @@ var TOPICS = [
|
|
|
2047
2928
|
title: "Show app names",
|
|
2048
2929
|
description: "Display labels beneath app bar icons"
|
|
2049
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
|
+
},
|
|
2050
2946
|
{
|
|
2051
2947
|
category: "notifications",
|
|
2052
2948
|
title: "Followed threads",
|
|
@@ -2100,6 +2996,7 @@ var TeamsSettings = class extends LitElement {
|
|
|
2100
2996
|
category: { state: true },
|
|
2101
2997
|
theme: { attribute: false },
|
|
2102
2998
|
followSettings: { attribute: false },
|
|
2999
|
+
notificationSettings: { attribute: false },
|
|
2103
3000
|
userName: { attribute: false },
|
|
2104
3001
|
fileOpenPreference: { attribute: false },
|
|
2105
3002
|
chatDensity: { attribute: false },
|
|
@@ -2115,6 +3012,7 @@ var TeamsSettings = class extends LitElement {
|
|
|
2115
3012
|
this.category = "general";
|
|
2116
3013
|
this.theme = "system";
|
|
2117
3014
|
this.followSettings = { started: true, replied: true };
|
|
3015
|
+
this.notificationSettings = { level: "all", sound: true };
|
|
2118
3016
|
this.userName = "";
|
|
2119
3017
|
this.fileOpenPreference = "teams";
|
|
2120
3018
|
this.chatDensity = "comfy";
|
|
@@ -2304,12 +3202,22 @@ var TeamsSettings = class extends LitElement {
|
|
|
2304
3202
|
?hidden=${!!this.query.trim() || this.category !== "notifications"}
|
|
2305
3203
|
>
|
|
2306
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
|
+
})}
|
|
2307
3218
|
<h3>Followed threads</h3>
|
|
2308
3219
|
<p class="description">Choose which conversations appear in Followed threads.</p>
|
|
2309
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>`)}
|
|
2310
|
-
<p class="description">
|
|
2311
|
-
Desktop, email and activity notifications are not available yet.
|
|
2312
|
-
</p>
|
|
2313
3221
|
</section>
|
|
2314
3222
|
<section
|
|
2315
3223
|
id="panel-files"
|
|
@@ -2464,8 +3372,8 @@ function loadConfig() {
|
|
|
2464
3372
|
var saveConfig = (config) => safeStorage.setItem("teams:config", JSON.stringify(config));
|
|
2465
3373
|
|
|
2466
3374
|
// raw-css:/home/runner/work/ooxml/ooxml/src/ui/src/teams/app/teams-app.css?raw
|
|
2467
|
-
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";
|
|
2468
|
-
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 = "") {
|
|
2469
3377
|
const thread = state.thread;
|
|
2470
3378
|
if (!thread) return nothing;
|
|
2471
3379
|
return html`<aside class="thread-pane" aria-label="Thread">
|
|
@@ -2483,6 +3391,7 @@ function threadPane(state, client, openFile, close) {
|
|
|
2483
3391
|
.messages=${[thread.root, ...thread.replies]}
|
|
2484
3392
|
.pinnedIds=${state.pinned.map((p) => p.message.id)}
|
|
2485
3393
|
self-id=${state.user.id}
|
|
3394
|
+
.highlightId=${highlightId}
|
|
2486
3395
|
@office-chat-pin=${(e) => client.pinMessage(e.detail.messageId)}
|
|
2487
3396
|
@office-chat-unpin=${(e) => client.unpinMessage(e.detail.messageId)}
|
|
2488
3397
|
@office-chat-react=${(e) => client.toggleReaction(e.detail.messageId, e.detail.emoji)}
|
|
@@ -2498,6 +3407,7 @@ function threadPane(state, client, openFile, close) {
|
|
|
2498
3407
|
.value=${state.draft.text}
|
|
2499
3408
|
.files=${state.draft.files}
|
|
2500
3409
|
.missingFiles=${state.draft.missingFiles}
|
|
3410
|
+
.mentionTargets=${state.mentionTargets}
|
|
2501
3411
|
@office-chat-draft=${(e) => client.setDraft(e.detail)}
|
|
2502
3412
|
placeholder="Reply in thread"
|
|
2503
3413
|
@office-chat-typing=${() => client.notifyTyping()}
|
|
@@ -2514,7 +3424,10 @@ function followedThreads(state, client, open, unreadOnly, filter) {
|
|
|
2514
3424
|
const threads = state.followedThreads.filter((thread) => !unreadOnly || thread.unread > 0);
|
|
2515
3425
|
return html`<section class="followed-threads" aria-label="Followed threads">
|
|
2516
3426
|
<h1>Followed threads</h1>
|
|
2517
|
-
<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>
|
|
2518
3431
|
<fieldset>
|
|
2519
3432
|
<legend>Automatically follow</legend>
|
|
2520
3433
|
<label
|
|
@@ -2946,6 +3859,60 @@ function watchActivity(target, onActivity, throttleMs = 1e3, now = Date.now) {
|
|
|
2946
3859
|
for (const name of ACTIVITY_EVENTS) target.removeEventListener(name, handler);
|
|
2947
3860
|
};
|
|
2948
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
|
+
}
|
|
2949
3916
|
|
|
2950
3917
|
// raw-css:/home/runner/work/ooxml/ooxml/src/ui/src/teams/app/add-tab-dialog.css?raw
|
|
2951
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";
|
|
@@ -3297,17 +4264,724 @@ function defineTeamsCreateChannelDialog(registry = globalThis.customElements) {
|
|
|
3297
4264
|
registry.define("teams-create-channel-dialog", TeamsCreateChannelDialog);
|
|
3298
4265
|
}
|
|
3299
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
|
+
|
|
3300
4965
|
// src/teams/app/teams-app.ts
|
|
3301
4966
|
var LOCAL_THEME = THEME_CSS.replaceAll(
|
|
3302
4967
|
':root[data-office-theme="dark"]',
|
|
3303
4968
|
':host([data-office-theme="dark"])'
|
|
3304
4969
|
).replaceAll(':root:not([data-office-theme="light"])', ':host([data-office-theme="system"])').replaceAll(":root", ":host([data-office-theme])");
|
|
3305
4970
|
var RAIL = [
|
|
4971
|
+
{ id: "activity", label: "Activity", icon: "bell" },
|
|
4972
|
+
{ id: "chat", label: "Chat", icon: "message" },
|
|
3306
4973
|
{ id: "teams", label: "Teams", icon: "users" },
|
|
3307
|
-
{ id: "
|
|
3308
|
-
{ id: "
|
|
3309
|
-
{ id: "
|
|
3310
|
-
{
|
|
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 }
|
|
3311
4985
|
];
|
|
3312
4986
|
var TeamsApp = class extends LitElement {
|
|
3313
4987
|
static styles = [unsafeCSS(LOCAL_THEME), unsafeCSS(teams_app_default)];
|
|
@@ -3323,6 +4997,10 @@ var TeamsApp = class extends LitElement {
|
|
|
3323
4997
|
preview: { state: true },
|
|
3324
4998
|
addingTab: { state: true },
|
|
3325
4999
|
creatingChannel: { state: true },
|
|
5000
|
+
newChat: { state: true },
|
|
5001
|
+
chatPeople: { state: true },
|
|
5002
|
+
meetingForm: { state: true },
|
|
5003
|
+
meetingDetails: { state: true },
|
|
3326
5004
|
rail: { state: true },
|
|
3327
5005
|
tab: { state: true },
|
|
3328
5006
|
panel: { state: true },
|
|
@@ -3330,6 +5008,9 @@ var TeamsApp = class extends LitElement {
|
|
|
3330
5008
|
settingsOpen: { state: true },
|
|
3331
5009
|
mobileView: { state: true },
|
|
3332
5010
|
toast: { state: true },
|
|
5011
|
+
activityToasts: { state: true },
|
|
5012
|
+
activityFilter: { state: true },
|
|
5013
|
+
highlightId: { state: true },
|
|
3333
5014
|
identity: { state: true },
|
|
3334
5015
|
followedUnreadOnly: { state: true },
|
|
3335
5016
|
theme: { state: true },
|
|
@@ -3337,10 +5018,18 @@ var TeamsApp = class extends LitElement {
|
|
|
3337
5018
|
chatDensity: { state: true },
|
|
3338
5019
|
showAppNames: { state: true }
|
|
3339
5020
|
};
|
|
3340
|
-
teams = new TeamsController(
|
|
5021
|
+
teams = new TeamsController(
|
|
5022
|
+
this,
|
|
5023
|
+
(text) => this.notify(text),
|
|
5024
|
+
(item) => this.announce(item)
|
|
5025
|
+
);
|
|
3341
5026
|
toastTimer;
|
|
5027
|
+
activityToastTimers = /* @__PURE__ */ new Map();
|
|
5028
|
+
highlightTimer;
|
|
3342
5029
|
stopActivity;
|
|
3343
5030
|
openRequest = 0;
|
|
5031
|
+
/** The channel last open in the Teams app, restored when you come back from Chat. */
|
|
5032
|
+
lastChannelId = "";
|
|
3344
5033
|
retainedTab;
|
|
3345
5034
|
themeStorageKey = "";
|
|
3346
5035
|
popoutRequested = new URL(globalThis.location?.href ?? "https://workspace.invalid").searchParams.get(
|
|
@@ -3363,6 +5052,10 @@ var TeamsApp = class extends LitElement {
|
|
|
3363
5052
|
this.retainedTab = void 0;
|
|
3364
5053
|
this.addingTab = false;
|
|
3365
5054
|
this.creatingChannel = false;
|
|
5055
|
+
this.newChat = false;
|
|
5056
|
+
this.chatPeople = false;
|
|
5057
|
+
this.meetingForm = null;
|
|
5058
|
+
this.meetingDetails = null;
|
|
3366
5059
|
this.rail = "teams";
|
|
3367
5060
|
this.tab = "posts";
|
|
3368
5061
|
this.panel = "";
|
|
@@ -3370,6 +5063,9 @@ var TeamsApp = class extends LitElement {
|
|
|
3370
5063
|
this.settingsOpen = false;
|
|
3371
5064
|
this.mobileView = "conversation";
|
|
3372
5065
|
this.toast = "";
|
|
5066
|
+
this.activityToasts = [];
|
|
5067
|
+
this.activityFilter = "all";
|
|
5068
|
+
this.highlightId = "";
|
|
3373
5069
|
this.identity = null;
|
|
3374
5070
|
this.followedUnreadOnly = false;
|
|
3375
5071
|
this.theme = "system";
|
|
@@ -3394,6 +5090,10 @@ var TeamsApp = class extends LitElement {
|
|
|
3394
5090
|
defineTeamsPinnedBar();
|
|
3395
5091
|
defineTeamsAddTabDialog();
|
|
3396
5092
|
defineTeamsCreateChannelDialog();
|
|
5093
|
+
defineTeamsNewChatDialog();
|
|
5094
|
+
defineTeamsChatPeopleDialog();
|
|
5095
|
+
defineTeamsMeetingDialog();
|
|
5096
|
+
defineTeamsMeetingDetails();
|
|
3397
5097
|
this.stopActivity = watchActivity(this.ownerDocument, () => this.teams.client?.noteActivity());
|
|
3398
5098
|
super.connectedCallback();
|
|
3399
5099
|
}
|
|
@@ -3423,6 +5123,8 @@ var TeamsApp = class extends LitElement {
|
|
|
3423
5123
|
this.tab = "posts";
|
|
3424
5124
|
this.addingTab = false;
|
|
3425
5125
|
this.creatingChannel = false;
|
|
5126
|
+
this.newChat = this.chatPeople = false;
|
|
5127
|
+
this.meetingForm = this.meetingDetails = null;
|
|
3426
5128
|
this.settingsOpen = false;
|
|
3427
5129
|
this.openRequest++;
|
|
3428
5130
|
const named = this.userName ? { id: this.userId || loadIdentity()?.id || crypto.randomUUID(), name: this.userName } : this.identity ?? loadIdentity();
|
|
@@ -3451,6 +5153,8 @@ var TeamsApp = class extends LitElement {
|
|
|
3451
5153
|
updated() {
|
|
3452
5154
|
this.setAttribute("data-chat-density", this.chatDensity);
|
|
3453
5155
|
const state = this.teams.state;
|
|
5156
|
+
if (state?.channels.some((c) => c.id === state.selectedChannelId))
|
|
5157
|
+
this.lastChannelId = state.selectedChannelId;
|
|
3454
5158
|
if (state?.thread && document.visibilityState === "visible" && this.renderRoot.querySelector(".thread-pane"))
|
|
3455
5159
|
this.teams.client?.markThreadRead(state.selectedChannelId, state.thread.root.id);
|
|
3456
5160
|
}
|
|
@@ -3459,6 +5163,25 @@ var TeamsApp = class extends LitElement {
|
|
|
3459
5163
|
clearTimeout(this.toastTimer);
|
|
3460
5164
|
this.toastTimer = setTimeout(() => this.toast = "", 4e3);
|
|
3461
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
|
+
}
|
|
3462
5185
|
// ---- intent -> client actions -----------------------------------------------------------
|
|
3463
5186
|
async openFile(a, mode) {
|
|
3464
5187
|
if (!this.canLeaveContent()) return;
|
|
@@ -3530,6 +5253,9 @@ var TeamsApp = class extends LitElement {
|
|
|
3530
5253
|
this.openRequest++;
|
|
3531
5254
|
this.preview = null;
|
|
3532
5255
|
clearTimeout(this.toastTimer);
|
|
5256
|
+
for (const timer of this.activityToastTimers.values()) clearTimeout(timer);
|
|
5257
|
+
this.activityToastTimers.clear();
|
|
5258
|
+
clearTimeout(this.highlightTimer);
|
|
3533
5259
|
this.stopActivity?.();
|
|
3534
5260
|
this.stopActivity = void 0;
|
|
3535
5261
|
super.disconnectedCallback();
|
|
@@ -3576,7 +5302,8 @@ var TeamsApp = class extends LitElement {
|
|
|
3576
5302
|
void this.teams.client?.openCall(channelId);
|
|
3577
5303
|
this.mobileView = "conversation";
|
|
3578
5304
|
this.meeting = true;
|
|
3579
|
-
|
|
5305
|
+
const target = channelId ?? this.teams.state?.selectedChannelId;
|
|
5306
|
+
this.rail = this.teams.state?.chats.some((c) => c.id === target) ? "chat" : "teams";
|
|
3580
5307
|
}
|
|
3581
5308
|
selectChannel(id) {
|
|
3582
5309
|
if (!this.closePreview()) return false;
|
|
@@ -3587,7 +5314,7 @@ var TeamsApp = class extends LitElement {
|
|
|
3587
5314
|
this.teams.client?.search("");
|
|
3588
5315
|
this.meeting = false;
|
|
3589
5316
|
this.tab = "posts";
|
|
3590
|
-
this.rail = "teams";
|
|
5317
|
+
this.rail = this.teams.state?.chats.some((c) => c.id === id) ? "chat" : "teams";
|
|
3591
5318
|
this.mobileView = "conversation";
|
|
3592
5319
|
return true;
|
|
3593
5320
|
}
|
|
@@ -3606,7 +5333,7 @@ var TeamsApp = class extends LitElement {
|
|
|
3606
5333
|
}
|
|
3607
5334
|
/** Which screen the compact shell shows: the channel or call list, or the content itself. */
|
|
3608
5335
|
mobileScreen(s) {
|
|
3609
|
-
const listed =
|
|
5336
|
+
const listed = ["teams", "calls", "activity", "chat", "calendar"].includes(this.rail);
|
|
3610
5337
|
return listed && this.mobileView === "list" && !(this.meeting && s.call) ? "list" : "content";
|
|
3611
5338
|
}
|
|
3612
5339
|
// ---- template ---------------------------------------------------------------------------
|
|
@@ -3634,11 +5361,12 @@ var TeamsApp = class extends LitElement {
|
|
|
3634
5361
|
<div class="body">
|
|
3635
5362
|
<office-ui-app-rail
|
|
3636
5363
|
.hideLabels=${!this.showAppNames}
|
|
3637
|
-
.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) } : {} }))}
|
|
3638
5365
|
selected=${this.rail}
|
|
3639
5366
|
@office-rail-select=${(e) => {
|
|
3640
5367
|
if (!this.closePreview()) return;
|
|
3641
5368
|
this.settingsOpen = false;
|
|
5369
|
+
if (e.detail.id === "teams") this.leaveChatSelection();
|
|
3642
5370
|
this.rail = e.detail.id;
|
|
3643
5371
|
this.meeting = false;
|
|
3644
5372
|
this.mobileView = "list";
|
|
@@ -3679,6 +5407,8 @@ var TeamsApp = class extends LitElement {
|
|
|
3679
5407
|
);
|
|
3680
5408
|
}}
|
|
3681
5409
|
.followSettings=${s.threadFollowSettings}
|
|
5410
|
+
.notificationSettings=${s.notificationSettings}
|
|
5411
|
+
@teams-settings-notifications=${(event) => this.teams.client?.setNotificationSettings(event.detail)}
|
|
3682
5412
|
.userName=${s.user.name}
|
|
3683
5413
|
@teams-settings-theme=${(event) => {
|
|
3684
5414
|
if (!["system", "light", "dark"].includes(event.detail.theme)) return;
|
|
@@ -3709,7 +5439,8 @@ var TeamsApp = class extends LitElement {
|
|
|
3709
5439
|
@teams-create-channel-close=${() => this.creatingChannel = false}
|
|
3710
5440
|
></teams-create-channel-dialog>
|
|
3711
5441
|
${this.toast ? html`<div class="toast" role="status">${this.toast}</div>` : nothing}
|
|
3712
|
-
|
|
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)}
|
|
3713
5444
|
<teams-add-tab-dialog
|
|
3714
5445
|
.open=${this.addingTab}
|
|
3715
5446
|
.client=${this.teams.client}
|
|
@@ -3788,7 +5519,10 @@ var TeamsApp = class extends LitElement {
|
|
|
3788
5519
|
}}
|
|
3789
5520
|
>
|
|
3790
5521
|
<strong>${h.message.authorName}</strong>
|
|
3791
|
-
<span class="in"
|
|
5522
|
+
<span class="in"
|
|
5523
|
+
>in
|
|
5524
|
+
${s.chats.some((c) => c.id === h.channelId) ? "" : "# "}${h.channelName}</span
|
|
5525
|
+
>
|
|
3792
5526
|
<span class="snippet">${h.message.text.slice(0, 100)}</span>
|
|
3793
5527
|
</button>
|
|
3794
5528
|
</li>`
|
|
@@ -3826,7 +5560,64 @@ var TeamsApp = class extends LitElement {
|
|
|
3826
5560
|
</header>
|
|
3827
5561
|
`;
|
|
3828
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
|
+
}
|
|
3829
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>`;
|
|
3830
5621
|
if (this.rail === "calls") {
|
|
3831
5622
|
const live2 = s.channels.filter((c) => c.live);
|
|
3832
5623
|
return html`
|
|
@@ -3882,13 +5673,18 @@ var TeamsApp = class extends LitElement {
|
|
|
3882
5673
|
}
|
|
3883
5674
|
);
|
|
3884
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();
|
|
3885
5679
|
return html`
|
|
3886
5680
|
${s.call && !this.meeting ? html`<div class="callbar">
|
|
3887
|
-
You are in a call in
|
|
5681
|
+
You are in a call in ${this.callHeading(s.call)}
|
|
3888
5682
|
<button
|
|
3889
5683
|
type="button"
|
|
3890
5684
|
@click=${() => {
|
|
3891
|
-
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;
|
|
3892
5688
|
}}
|
|
3893
5689
|
>
|
|
3894
5690
|
Return to call
|
|
@@ -3899,52 +5695,57 @@ var TeamsApp = class extends LitElement {
|
|
|
3899
5695
|
}
|
|
3900
5696
|
conversation(s, compact = false) {
|
|
3901
5697
|
const channel = s.channel;
|
|
5698
|
+
const chat = s.chats.find((x) => x.id === s.selectedChannelId);
|
|
3902
5699
|
const c = this.teams.client;
|
|
3903
5700
|
const compose = s.editing ?? s.replyingTo;
|
|
3904
5701
|
const sharedTab = s.tabs.find((t) => t.id === this.tab);
|
|
3905
5702
|
if (sharedTab) this.retainedTab = sharedTab;
|
|
3906
5703
|
const activeTab = sharedTab ?? (this.retainedTab?.id === this.tab && this.retainedTab.channelId === s.selectedChannelId ? this.retainedTab : void 0);
|
|
3907
5704
|
return html`
|
|
3908
|
-
${compact ? nothing :
|
|
3909
|
-
|
|
3910
|
-
|
|
3911
|
-
|
|
3912
|
-
|
|
3913
|
-
|
|
3914
|
-
|
|
3915
|
-
|
|
3916
|
-
|
|
3917
|
-
|
|
3918
|
-
|
|
3919
|
-
|
|
3920
|
-
|
|
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(
|
|
3921
5722
|
(t) => html`<button
|
|
3922
|
-
|
|
3923
|
-
|
|
3924
|
-
|
|
3925
|
-
|
|
3926
|
-
|
|
3927
|
-
|
|
3928
|
-
|
|
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>`
|
|
3929
5730
|
)}
|
|
3930
|
-
|
|
3931
|
-
|
|
3932
|
-
|
|
3933
|
-
|
|
3934
|
-
|
|
3935
|
-
|
|
3936
|
-
|
|
3937
|
-
|
|
3938
|
-
|
|
3939
|
-
|
|
3940
|
-
|
|
3941
|
-
|
|
3942
|
-
|
|
3943
|
-
|
|
3944
|
-
|
|
3945
|
-
|
|
3946
|
-
|
|
3947
|
-
|
|
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 () => {
|
|
3948
5749
|
if (s.thread?.root.tabId === sharedTab.id) {
|
|
3949
5750
|
await this.closeThread();
|
|
3950
5751
|
return;
|
|
@@ -3957,49 +5758,51 @@ var TeamsApp = class extends LitElement {
|
|
|
3957
5758
|
await this.updateComplete;
|
|
3958
5759
|
this.shadowRoot?.querySelector("[data-thread-heading]")?.focus();
|
|
3959
5760
|
}}
|
|
3960
|
-
|
|
3961
|
-
|
|
3962
|
-
|
|
3963
|
-
|
|
3964
|
-
|
|
3965
|
-
|
|
3966
|
-
|
|
3967
|
-
|
|
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) => {
|
|
3968
5769
|
if (event.detail.command === "rename-tab") {
|
|
3969
5770
|
const name = globalThis.prompt?.("Tab name", sharedTab.name)?.trim();
|
|
3970
5771
|
if (name) c?.renameTab(sharedTab.id, name);
|
|
3971
5772
|
} else if (event.detail.command === "remove-tab") {
|
|
3972
5773
|
if (!this.canLeaveContent()) return;
|
|
3973
|
-
if (globalThis.confirm?.(
|
|
5774
|
+
if (globalThis.confirm?.(
|
|
5775
|
+
`Remove ${sharedTab.name} from this channel?`
|
|
5776
|
+
) === true && c?.removeTab(sharedTab.id)) {
|
|
3974
5777
|
this.openRequest++;
|
|
3975
5778
|
this.preview = null;
|
|
3976
5779
|
this.tab = "posts";
|
|
3977
5780
|
}
|
|
3978
5781
|
}
|
|
3979
5782
|
}}
|
|
3980
|
-
|
|
3981
|
-
|
|
3982
|
-
|
|
3983
|
-
|
|
3984
|
-
|
|
3985
|
-
|
|
3986
|
-
|
|
3987
|
-
|
|
3988
|
-
|
|
3989
|
-
|
|
3990
|
-
|
|
3991
|
-
|
|
3992
|
-
|
|
3993
|
-
|
|
3994
|
-
|
|
3995
|
-
|
|
3996
|
-
|
|
3997
|
-
|
|
3998
|
-
|
|
3999
|
-
|
|
4000
|
-
|
|
4001
|
-
|
|
4002
|
-
|
|
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>`}
|
|
4003
5806
|
${c ? messageTransfers(s, c) : nothing}
|
|
4004
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}
|
|
4005
5808
|
${activeTab && !compact ? html`<div
|
|
@@ -4019,7 +5822,8 @@ var TeamsApp = class extends LitElement {
|
|
|
4019
5822
|
s,
|
|
4020
5823
|
c,
|
|
4021
5824
|
(attachment) => void this.openFile(attachment),
|
|
4022
|
-
() => void this.closeThread()
|
|
5825
|
+
() => void this.closeThread(),
|
|
5826
|
+
this.highlightId
|
|
4023
5827
|
) : nothing}
|
|
4024
5828
|
</div>` : this.tab === "files" && !compact ? this.fileList(s.files, s) : html`<div class="conversation-grid" data-thread=${String(!!s.thread && !compact)}>
|
|
4025
5829
|
<div class="conversation-main">
|
|
@@ -4033,6 +5837,9 @@ var TeamsApp = class extends LitElement {
|
|
|
4033
5837
|
.replyCounts=${compact ? {} : s.replyCounts}
|
|
4034
5838
|
.pinnedIds=${s.pinned.map((p) => p.message.id)}
|
|
4035
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)}
|
|
4036
5843
|
@office-chat-pin=${(e) => c?.pinMessage(e.detail.messageId)}
|
|
4037
5844
|
@office-chat-unpin=${(e) => c?.unpinMessage(e.detail.messageId)}
|
|
4038
5845
|
@office-chat-react=${(e) => c?.toggleReaction(e.detail.messageId, e.detail.emoji)}
|
|
@@ -4049,9 +5856,10 @@ var TeamsApp = class extends LitElement {
|
|
|
4049
5856
|
.value=${s.draft.text}
|
|
4050
5857
|
.files=${s.draft.files}
|
|
4051
5858
|
.missingFiles=${s.draft.missingFiles}
|
|
5859
|
+
.mentionTargets=${s.mentionTargets}
|
|
4052
5860
|
@office-chat-draft=${(e) => c?.setDraft(e.detail)}
|
|
4053
5861
|
?disabled=${!channel}
|
|
4054
|
-
placeholder=${channel ? `Message # ${channel.name}` : "Create a channel first"}
|
|
5862
|
+
placeholder=${chat ? `Message ${chat.title}` : channel ? `Message # ${channel.name}` : "Create a channel first"}
|
|
4055
5863
|
@office-chat-typing=${() => c?.notifyTyping()}
|
|
4056
5864
|
@office-chat-cancel=${() => c?.cancelCompose()}
|
|
4057
5865
|
@office-chat-send=${(e) => void c?.send(e.detail)}
|
|
@@ -4062,7 +5870,8 @@ var TeamsApp = class extends LitElement {
|
|
|
4062
5870
|
s,
|
|
4063
5871
|
c,
|
|
4064
5872
|
(attachment) => void this.openFile(attachment),
|
|
4065
|
-
() => void this.closeThread()
|
|
5873
|
+
() => void this.closeThread(),
|
|
5874
|
+
this.highlightId
|
|
4066
5875
|
) : nothing}
|
|
4067
5876
|
</div>`}
|
|
4068
5877
|
`;
|
|
@@ -4074,17 +5883,41 @@ var TeamsApp = class extends LitElement {
|
|
|
4074
5883
|
this.addingTab = false;
|
|
4075
5884
|
this.creatingChannel = false;
|
|
4076
5885
|
}
|
|
4077
|
-
/** Scroll a
|
|
5886
|
+
/** Scroll a message into view and highlight it, opening its thread when it is a reply. */
|
|
4078
5887
|
async revealMessage(id) {
|
|
4079
5888
|
const message = this.teams.state?.messages.find((m) => m.id === id);
|
|
4080
5889
|
if (!message) return;
|
|
4081
|
-
if (message.replyTo)
|
|
4082
|
-
|
|
4083
|
-
const
|
|
4084
|
-
|
|
4085
|
-
|
|
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);
|
|
4086
5897
|
row?.scrollIntoView({ block: "center" });
|
|
4087
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);
|
|
4088
5921
|
}
|
|
4089
5922
|
async openThread(id, action) {
|
|
4090
5923
|
const client = this.teams.client;
|
|
@@ -4095,6 +5928,166 @@ var TeamsApp = class extends LitElement {
|
|
|
4095
5928
|
await this.updateComplete;
|
|
4096
5929
|
this.shadowRoot?.querySelector("[data-thread-heading]")?.focus();
|
|
4097
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
|
+
}
|
|
4098
6091
|
async resumeDraft(context) {
|
|
4099
6092
|
if (!this.closePreview() || !this.teams.client?.openDraft(context)) return;
|
|
4100
6093
|
this.rail = "teams";
|
|
@@ -4163,7 +6156,7 @@ var TeamsApp = class extends LitElement {
|
|
|
4163
6156
|
if (call.phase === "prejoin")
|
|
4164
6157
|
return html`
|
|
4165
6158
|
<office-ui-prejoin
|
|
4166
|
-
heading=${
|
|
6159
|
+
heading=${this.callHeading(call)}
|
|
4167
6160
|
name=${s.user.name}
|
|
4168
6161
|
.preview=${call.preview}
|
|
4169
6162
|
?audio=${call.prejoin.audio}
|
|
@@ -4177,7 +6170,7 @@ var TeamsApp = class extends LitElement {
|
|
|
4177
6170
|
return html`
|
|
4178
6171
|
<section class="meeting">
|
|
4179
6172
|
<office-ui-call-controls
|
|
4180
|
-
heading=${
|
|
6173
|
+
heading=${this.callHeading(call)}
|
|
4181
6174
|
started-at=${call.startedAt ?? 0}
|
|
4182
6175
|
?mic=${self?.state.audio}
|
|
4183
6176
|
?camera=${self?.state.video}
|
|
@@ -4262,22 +6255,32 @@ function createTeams(options) {
|
|
|
4262
6255
|
var TEAMS_TAGS = [
|
|
4263
6256
|
"office-ui-avatar",
|
|
4264
6257
|
"office-ui-app-rail",
|
|
6258
|
+
"office-ui-activity-feed",
|
|
4265
6259
|
"office-ui-channel-list",
|
|
4266
6260
|
"office-ui-chat-list",
|
|
4267
6261
|
"office-ui-chat-composer",
|
|
4268
6262
|
"office-ui-prejoin",
|
|
4269
6263
|
"office-ui-call-grid",
|
|
4270
|
-
"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"
|
|
4271
6269
|
];
|
|
4272
6270
|
function registerTeams() {
|
|
4273
6271
|
defineAvatar();
|
|
4274
6272
|
defineAppRail();
|
|
6273
|
+
defineActivityFeed();
|
|
4275
6274
|
defineChannelList();
|
|
4276
6275
|
defineChatList();
|
|
4277
6276
|
defineChatComposer();
|
|
4278
6277
|
definePrejoin();
|
|
4279
6278
|
defineCallGrid();
|
|
4280
6279
|
defineCallControls();
|
|
6280
|
+
defineChatSidebar();
|
|
6281
|
+
definePeoplePicker();
|
|
6282
|
+
defineCalendarView();
|
|
6283
|
+
defineCalendarAgenda();
|
|
4281
6284
|
}
|
|
4282
6285
|
|
|
4283
|
-
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 };
|