@leavepulse/ui 0.78.3 → 0.80.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assets/{LpCommandPalette-DDJKICKh.css → LpCommandPalette-C1LRFzbN.css} +19 -19
- package/dist/chunks/{ContextMenuItems-DmaKSJVv.js → ContextMenuItems-DLK4q-mm.js} +1 -1
- package/dist/chunks/{DropzoneLinkField-CyE7TJ5f.js → DropzoneLinkField-CcJu8De3.js} +1 -1
- package/dist/chunks/{FieldLeading-mr81aEAP.js → FieldLeading-CldGLINn.js} +1 -1
- package/dist/chunks/{FieldWrapper-DnuMTrqW.js → FieldWrapper-Cj8ZgoKp.js} +1 -1
- package/dist/chunks/{IconCloseButton-COZEsa9u.js → IconCloseButton-CV4iHRpy.js} +1 -1
- package/dist/chunks/{LayoutCanvas-CZKOltfA.js → LayoutCanvas-BQbq7Ekw.js} +1 -1
- package/dist/chunks/{LayoutNode-D2f7v683.js → LayoutNode-BMedRk3g.js} +1 -1
- package/dist/chunks/{LpActionBar-BGMk5KoG.js → LpActionBar-C7g52Cyo.js} +1 -1
- package/dist/chunks/{LpAddressInput-ft8fQOGx.js → LpAddressInput-1uakhQk5.js} +7 -7
- package/dist/chunks/{LpAlert-CjvTZIKF.js → LpAlert-DWFeR82L.js} +1 -1
- package/dist/chunks/{LpAppShell-DRHoQtr-.js → LpAppShell-InIK01Nn.js} +4 -4
- package/dist/chunks/{LpAutocomplete-CrZbd0uv.js → LpAutocomplete-DY3LvpB9.js} +4 -4
- package/dist/chunks/{LpAvatar-cQVsNk6F.js → LpAvatar-CEZmMcGh.js} +1 -1
- package/dist/chunks/{LpBadge-D5QQdDQ_.js → LpBadge-C_VqLHtg.js} +1 -1
- package/dist/chunks/{LpBottomNav-zxLGGbjm.js → LpBottomNav-4I89sPDZ.js} +1 -1
- package/dist/chunks/{LpBreadcrumbs-CIIBsygI.js → LpBreadcrumbs-1BBzrfxG.js} +1 -1
- package/dist/chunks/{LpCalendar-D4-LVjfF.js → LpCalendar-D2dcXjUK.js} +1 -1
- package/dist/chunks/{LpCheckbox-CCWCwD0y.js → LpCheckbox-CN-MEnbX.js} +2 -2
- package/dist/chunks/{LpCodeBlock-DBqy4RLd.js → LpCodeBlock-Cj7zk4QE.js} +2 -2
- package/dist/chunks/{LpCodeDisplay-D59uPwRb.js → LpCodeDisplay-COzosm77.js} +4 -4
- package/dist/chunks/{LpColorPicker-BONURBFN.js → LpColorPicker-BezW6DX1.js} +3 -3
- package/dist/chunks/{LpConfirmDialog-CnrmzkuN.js → LpConfirmDialog-D9GkDMYr.js} +2 -2
- package/dist/chunks/{LpConfirmHost-CwbObVGH.js → LpConfirmHost-BH7kf0dm.js} +1 -1
- package/dist/chunks/{LpContextMenu-Bx_IhQDS.js → LpContextMenu-bn5bc9t7.js} +2 -2
- package/dist/chunks/{LpContextSwitcher-1C1tExdl.js → LpContextSwitcher-CGr6ZAuq.js} +2 -2
- package/dist/chunks/{LpCopyButton-sAMvWeLP.js → LpCopyButton-BSr6YaFR.js} +1 -1
- package/dist/chunks/{LpDataList-CaVfsozH.js → LpDataList-Cv7ZUlyy.js} +2 -2
- package/dist/chunks/{LpDatePicker-C2AOtxgF.js → LpDatePicker-CR7vsb5M.js} +5 -5
- package/dist/chunks/{LpDateRangePicker-CiXdIAyh.js → LpDateRangePicker-B9fRO3G6.js} +3 -3
- package/dist/chunks/{LpDisclosure-DG7JCo-d.js → LpDisclosure-CE4mneaE.js} +1 -1
- package/dist/chunks/{LpDrawer-DXNQFpAA.js → LpDrawer-DU_5MqBz.js} +1 -1
- package/dist/chunks/{LpDropdownMenu-CLzxIOgM.js → LpDropdownMenu-_u6GPWhp.js} +2 -2
- package/dist/chunks/{LpEditable-DVT0Rh8F.js → LpEditable-DYoMayjt.js} +2 -2
- package/dist/chunks/{LpEmptyState-DurPF001.js → LpEmptyState-DpdHeSfz.js} +1 -1
- package/dist/chunks/{LpFieldNotice-DJ10cYIo.js → LpFieldNotice-DONFCWV7.js} +1 -1
- package/dist/chunks/{LpFileTree-CpNurwZp.js → LpFileTree-f5ktGqsN.js} +4 -4
- package/dist/chunks/{LpFileTreeNode-DdF8Cq-s.js → LpFileTreeNode-nbp-JwV9.js} +4 -4
- package/dist/chunks/{LpFormField-BKYn9dyP.js → LpFormField-Bz50_LZW.js} +1 -1
- package/dist/chunks/{LpHintLayer-BeKRsRon.js → LpHintLayer-B6bA5Cb_.js} +1 -1
- package/dist/chunks/{LpHints-qf3xYsza.js → LpHints-DyJ5hVcr.js} +3 -3
- package/dist/chunks/{LpIcon-C6JpQ5td.js → LpIcon-BCQLuHSP.js} +1 -1
- package/dist/chunks/{LpInfraNode-Bb5nbuFY.js → LpInfraNode-BS1RXYAs.js} +2 -2
- package/dist/chunks/{LpInput-CbI7z5fQ.js → LpInput-BjbXdjcW.js} +3 -3
- package/dist/chunks/{LpInspector-DO3fTCQ1.js → LpInspector-BIyJyM6r.js} +4 -4
- package/dist/chunks/{LpLightbox-CtDTQV01.js → LpLightbox-CSAJuUaJ.js} +2 -2
- package/dist/chunks/{LpLogInspector-CcSJSGan.js → LpLogInspector-OJEz1vod.js} +2 -2
- package/dist/chunks/{LpLogViewer-CWu49Dko.js → LpLogViewer-CRLwQpk0.js} +6 -6
- package/dist/chunks/{LpMapPicker-D5_YLLBC.js → LpMapPicker-DW2EnrCJ.js} +1 -1
- package/dist/chunks/{LpMediaGallery-BYEwySoF.js → LpMediaGallery-BNEYctDP.js} +3 -3
- package/dist/chunks/{LpModal-DDvrSAnf.js → LpModal-DdTqdf4x.js} +1 -1
- package/dist/chunks/{LpModalNav-DI3BW5ff.js → LpModalNav-BL7Dp0om.js} +3 -3
- package/dist/chunks/LpNotificationBell-d0F6MWxD.js +163 -0
- package/dist/chunks/LpNotificationFeed-BIe5lapb.js +470 -0
- package/dist/chunks/{LpNumberField-C8LfUz_R.js → LpNumberField-D5Dx-hzD.js} +3 -3
- package/dist/chunks/{LpOtpInput-B1X9l9no.js → LpOtpInput-BVl74Lfl.js} +1 -1
- package/dist/chunks/{LpPagination-snQ020xQ.js → LpPagination-D0wb-Uru.js} +1 -1
- package/dist/chunks/{LpPaletteTheme-B-xuZiKK.js → LpPaletteTheme-DdilCBXA.js} +2 -2
- package/dist/chunks/{LpPasswordInput-Duc_3wPv.js → LpPasswordInput-DUtqWMkA.js} +2 -2
- package/dist/chunks/{LpPhoneInput-CctcRK9K.js → LpPhoneInput-CalRjkqc.js} +3 -3
- package/dist/chunks/{LpPie-oVNHjsKD.js → LpPie-BVAEmVBT.js} +2 -2
- package/dist/chunks/{LpPipeline-BSXT6oUJ.js → LpPipeline-Dk7_sRP1.js} +2 -2
- package/dist/chunks/{LpQuota-CgWPgdVt.js → LpQuota-DKx0IZYA.js} +1 -1
- package/dist/chunks/{LpRadioGroup-DTM0nd9G.js → LpRadioGroup-E3SP6j9h.js} +2 -2
- package/dist/chunks/{LpRangeCalendar-BrqlGZzE.js → LpRangeCalendar-BFJFaen4.js} +1 -1
- package/dist/chunks/{LpRangeSlider-DJsEZXad.js → LpRangeSlider-b6ipywRB.js} +1 -1
- package/dist/chunks/{LpRepeater-Czib3rmv.js → LpRepeater-BLrw62Bh.js} +2 -2
- package/dist/chunks/{LpSecretField-BtlCk3IH.js → LpSecretField-BV8BNjKc.js} +5 -5
- package/dist/chunks/{LpSection-BfteipxU.js → LpSection-CghNNxIv.js} +1 -1
- package/dist/chunks/{LpSegmented-sskrJKJJ.js → LpSegmented-DjvrHL_G.js} +2 -2
- package/dist/chunks/{LpSelect-JFZehOkd.js → LpSelect-DYPimzAZ.js} +4 -4
- package/dist/chunks/{LpSidebar-CvRvVBTt.js → LpSidebar-D3S8rYFf.js} +4 -4
- package/dist/chunks/{LpSidebarNav-CE0jQS8i.js → LpSidebarNav-Dlse8vxT.js} +3 -3
- package/dist/chunks/{LpSidebarRow-DOTg1txp.js → LpSidebarRow-Cqd_6tGG.js} +3 -3
- package/dist/chunks/{LpSlider-C4ilCtZX.js → LpSlider-B9XIC75O.js} +1 -1
- package/dist/chunks/{LpStat-DPjc6_fX.js → LpStat-kyLRmX-m.js} +2 -2
- package/dist/chunks/{LpStatus-DGJFwk5F.js → LpStatus-szB2dWzM.js} +1 -1
- package/dist/chunks/{LpStepMark-Dw2MRTrt.js → LpStepMark-DP3CDSm9.js} +1 -1
- package/dist/chunks/{LpStepper-DNnh7lCu.js → LpStepper-BS3iaJIz.js} +1 -1
- package/dist/chunks/{LpSwitch-DyAYTchz.js → LpSwitch-DRFy8RNr.js} +1 -1
- package/dist/chunks/{LpTabFace-DQoV8mQG.js → LpTabFace-C9-OperL.js} +2 -2
- package/dist/chunks/{LpTableFilter-CJg5eIcV.js → LpTableFilter-CEIwLupk.js} +2 -2
- package/dist/chunks/{LpTagsInput-CkNxpNYa.js → LpTagsInput-ClDeF_aU.js} +5 -5
- package/dist/chunks/{LpTextarea-CFK_5QB8.js → LpTextarea-DEY6pUBy.js} +1 -1
- package/dist/chunks/{LpThemeStudio-R-wohbCY.js → LpThemeStudio-WY72Z1Db.js} +5 -5
- package/dist/chunks/{LpThemeSwitcher-Bzy15MCP.js → LpThemeSwitcher-9uCH9c-K.js} +3 -3
- package/dist/chunks/{LpTimeField-B5n0m8m0.js → LpTimeField-BmgxCzQO.js} +2 -2
- package/dist/chunks/{LpToaster-Ct_ZOhCh.js → LpToaster-DLKO-efn.js} +2 -2
- package/dist/chunks/{LpTopologyCanvas-BNgw9RyZ.js → LpTopologyCanvas-B-PhPa7k.js} +4 -4
- package/dist/chunks/{LpTour-ClKYhx4h.js → LpTour-ODlBcat2.js} +1 -1
- package/dist/chunks/{LpTruncate-ellq9RYM.js → LpTruncate--nhT0iUo.js} +1 -1
- package/dist/chunks/{LpWindow-B8YSRVTH.js → LpWindow-DJxE8Zl-.js} +2 -2
- package/dist/chunks/{LpWorkspaceSwitcher-ugv-fyig.js → LpWorkspaceSwitcher-Bpf41Bw5.js} +3 -3
- package/dist/chunks/{MenuTitle-Bh5dAdV1.js → MenuTitle-CMjvLsvC.js} +1 -1
- package/dist/chunks/{OptionContent-CGb8QlHA.js → OptionContent-DY8NaG8s.js} +1 -1
- package/dist/chunks/{PickerField-BM1dyafh.js → PickerField-CgfkaBgg.js} +1 -1
- package/dist/chunks/{RevealToggle-D_iyrB8d.js → RevealToggle-CPMXxaKv.js} +1 -1
- package/dist/chunks/{TourCard-DAzTYfav.js → TourCard-D4b3lMHi.js} +1 -1
- package/dist/chunks/icons-C1vppR4f.js +59 -0
- package/dist/component-names.d.ts +1 -1
- package/dist/components/ContextMenuItems.vue.js +1 -1
- package/dist/components/DropzoneLinkField.vue.js +1 -1
- package/dist/components/FieldLeading.vue.js +1 -1
- package/dist/components/FieldWrapper.vue.js +1 -1
- package/dist/components/IconCloseButton.vue.js +1 -1
- package/dist/components/LayoutCanvas.vue.js +1 -1
- package/dist/components/LayoutNode.vue.js +1 -1
- package/dist/components/LpActionBar.vue.js +1 -1
- package/dist/components/LpAddressInput.vue.js +1 -1
- package/dist/components/LpAlert.vue.js +1 -1
- package/dist/components/LpAppShell.vue.js +1 -1
- package/dist/components/LpAutocomplete.vue.js +1 -1
- package/dist/components/LpAvatar.vue.js +1 -1
- package/dist/components/LpBadge.vue.js +1 -1
- package/dist/components/LpBottomNav.vue.js +1 -1
- package/dist/components/LpBreadcrumbs.vue.js +1 -1
- package/dist/components/LpCalendar.vue.js +1 -1
- package/dist/components/LpChart.vue.js +2 -2
- package/dist/components/LpCheckbox.vue.js +1 -1
- package/dist/components/LpCodeBlock.vue.js +1 -1
- package/dist/components/LpCodeDisplay.vue.js +1 -1
- package/dist/components/LpColorPicker.vue.js +1 -1
- package/dist/components/LpCommandPalette.vue.d.ts +22 -1
- package/dist/components/LpCommandPalette.vue.js +36 -16
- package/dist/components/LpConfirmDialog.vue.js +1 -1
- package/dist/components/LpConfirmHost.vue.js +1 -1
- package/dist/components/LpContextMenu.vue.js +1 -1
- package/dist/components/LpContextSwitcher.vue.js +1 -1
- package/dist/components/LpCopyButton.vue.js +1 -1
- package/dist/components/LpDataList.vue.js +1 -1
- package/dist/components/LpDatePicker.vue.js +1 -1
- package/dist/components/LpDateRangePicker.vue.js +1 -1
- package/dist/components/LpDisclosure.vue.js +1 -1
- package/dist/components/LpDock.vue.js +1 -1
- package/dist/components/LpDrawer.vue.js +1 -1
- package/dist/components/LpDropdownMenu.vue.js +1 -1
- package/dist/components/LpDropzone.vue.js +2 -2
- package/dist/components/LpEditable.vue.js +1 -1
- package/dist/components/LpEmptyState.vue.js +1 -1
- package/dist/components/LpFieldNotice.vue.js +1 -1
- package/dist/components/LpFileTree.vue.js +1 -1
- package/dist/components/LpFileTreeNode.vue.js +1 -1
- package/dist/components/LpFormField.vue.js +1 -1
- package/dist/components/LpHintLayer.vue.js +1 -1
- package/dist/components/LpHints.vue.js +1 -1
- package/dist/components/LpIcon.vue.js +1 -1
- package/dist/components/LpImageEditor.vue.js +1 -1
- package/dist/components/LpInfraNode.vue.js +1 -1
- package/dist/components/LpInput.vue.js +1 -1
- package/dist/components/LpInspector.vue.js +1 -1
- package/dist/components/LpLightbox.vue.js +1 -1
- package/dist/components/LpLogInspector.vue.js +1 -1
- package/dist/components/LpLogViewer.vue.js +1 -1
- package/dist/components/LpMapPicker.vue.js +1 -1
- package/dist/components/LpMediaGallery.vue.js +1 -1
- package/dist/components/LpModal.vue.js +1 -1
- package/dist/components/LpModalNav.vue.js +1 -1
- package/dist/components/LpNotificationBell.vue.d.ts +28 -64
- package/dist/components/LpNotificationBell.vue.js +1 -1
- package/dist/components/LpNotificationFeed.vue.d.ts +78 -0
- package/dist/components/LpNotificationFeed.vue.js +4 -0
- package/dist/components/LpNumberField.vue.js +1 -1
- package/dist/components/LpOtpInput.vue.js +1 -1
- package/dist/components/LpPagination.vue.js +1 -1
- package/dist/components/LpPaletteFacts.vue.js +1 -1
- package/dist/components/LpPaletteHeader.vue.js +2 -2
- package/dist/components/LpPaletteTheme.vue.js +1 -1
- package/dist/components/LpPasswordInput.vue.js +1 -1
- package/dist/components/LpPhoneInput.vue.js +1 -1
- package/dist/components/LpPie.vue.js +1 -1
- package/dist/components/LpPipeline.vue.js +1 -1
- package/dist/components/LpQuota.vue.js +1 -1
- package/dist/components/LpRadioGroup.vue.js +1 -1
- package/dist/components/LpRangeCalendar.vue.js +1 -1
- package/dist/components/LpRangeSlider.vue.js +1 -1
- package/dist/components/LpRepeater.vue.js +1 -1
- package/dist/components/LpSecretField.vue.js +1 -1
- package/dist/components/LpSection.vue.js +1 -1
- package/dist/components/LpSegmented.vue.js +1 -1
- package/dist/components/LpSelect.vue.js +1 -1
- package/dist/components/LpShortcutsDialog.vue.js +1 -1
- package/dist/components/LpSidebar.vue.js +1 -1
- package/dist/components/LpSidebarNav.vue.js +1 -1
- package/dist/components/LpSidebarRow.vue.js +1 -1
- package/dist/components/LpSlider.vue.js +1 -1
- package/dist/components/LpStat.vue.js +1 -1
- package/dist/components/LpStatus.vue.js +1 -1
- package/dist/components/LpStepMark.vue.js +1 -1
- package/dist/components/LpStepper.vue.js +1 -1
- package/dist/components/LpSwitch.vue.js +1 -1
- package/dist/components/LpTabFace.vue.js +1 -1
- package/dist/components/LpTable.vue.js +9 -9
- package/dist/components/LpTableFilter.vue.js +1 -1
- package/dist/components/LpTabs.vue.js +2 -2
- package/dist/components/LpTagsInput.vue.js +1 -1
- package/dist/components/LpTextarea.vue.js +1 -1
- package/dist/components/LpThemeStudio.vue.js +1 -1
- package/dist/components/LpThemeSwitcher.vue.js +1 -1
- package/dist/components/LpTimeField.vue.js +1 -1
- package/dist/components/LpToaster.vue.js +1 -1
- package/dist/components/LpTopologyCanvas.vue.js +1 -1
- package/dist/components/LpTour.vue.js +1 -1
- package/dist/components/LpTruncate.vue.js +1 -1
- package/dist/components/LpWindow.vue.js +1 -1
- package/dist/components/LpWorkspaceSwitcher.vue.js +1 -1
- package/dist/components/MenuTitle.vue.js +1 -1
- package/dist/components/OptionContent.vue.js +1 -1
- package/dist/components/PickerField.vue.js +1 -1
- package/dist/components/RevealToggle.vue.js +1 -1
- package/dist/components/TourCard.vue.js +1 -1
- package/dist/components/commandPalette.d.ts +14 -0
- package/dist/components/commandPalette.js +42 -0
- package/dist/components/menuWhen.js +1 -1
- package/dist/components/notifications.d.ts +156 -0
- package/dist/components/notifications.js +59 -0
- package/dist/components/relativeTime.js +6 -1
- package/dist/composables/useAsyncTask.d.ts +6 -1
- package/dist/composables/useAsyncTask.js +4 -1
- package/dist/icons-all.js +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +208 -206
- package/package.json +1 -1
- package/src/component-names.ts +1 -0
- package/src/components/LpCommandPalette.vue +64 -14
- package/src/components/LpNotificationBell.vue +105 -279
- package/src/components/LpNotificationFeed.vue +404 -0
- package/src/components/commandPalette.ts +62 -0
- package/src/components/notifications.ts +197 -0
- package/src/components/relativeTime.ts +13 -1
- package/src/composables/useAsyncTask.ts +10 -2
- package/src/index.ts +6 -1
- package/src/kit-icons.ts +1 -1
- package/dist/chunks/LpNotificationBell-DUbVyK6R.js +0 -311
- package/dist/chunks/icons-CYfcpSDS.js +0 -59
|
@@ -202,3 +202,17 @@ export declare function modeChipLabel(command: {
|
|
|
202
202
|
label: string;
|
|
203
203
|
modeLabel?: string;
|
|
204
204
|
}): string;
|
|
205
|
+
/** What a fetcher may hand back: the rows, a promise of them, or batches of them. */
|
|
206
|
+
export type FetchedRows<T> = T[] | Promise<T[]> | AsyncIterable<T[]>;
|
|
207
|
+
/**
|
|
208
|
+
* Settles a fetcher's answer into its final rows. A plain list or a promise is
|
|
209
|
+
* passed through; batches are walked one by one, each handed to `onBatch` as
|
|
210
|
+
* it lands (each is the whole list so far, replacing the one before), and the
|
|
211
|
+
* last is the result — no batches at all is an empty list.
|
|
212
|
+
*
|
|
213
|
+
* An abort stops the walk at once rather than at the next batch: the iterator
|
|
214
|
+
* is closed (`return()`; a generator parked in an `await` closes at its next
|
|
215
|
+
* `yield`, running its `finally` there) and the wait for the pending batch is
|
|
216
|
+
* dropped. A batch that lands afterwards is not handed on.
|
|
217
|
+
*/
|
|
218
|
+
export declare function settleFetched<T>(result: FetchedRows<T>, signal: AbortSignal, onBatch: (rows: T[]) => void): Promise<T[]>;
|
|
@@ -138,6 +138,47 @@ function modeChipLabel(command) {
|
|
|
138
138
|
if (!command.label.includes("{query}")) return command.label;
|
|
139
139
|
return command.label.replace(/\s*["'“”«»]?\{query\}["'“”«»]?/g, "").replace(/\s+(for|in|on|:)$/i, "").trim();
|
|
140
140
|
}
|
|
141
|
+
function isAsyncIterable(value) {
|
|
142
|
+
return value != null && typeof value[Symbol.asyncIterator] === "function";
|
|
143
|
+
}
|
|
144
|
+
async function settleFetched(result, signal, onBatch) {
|
|
145
|
+
if (!isAsyncIterable(result)) return result;
|
|
146
|
+
const iterator = result[Symbol.asyncIterator]();
|
|
147
|
+
let closed = false;
|
|
148
|
+
const close = () => {
|
|
149
|
+
if (closed) return;
|
|
150
|
+
closed = true;
|
|
151
|
+
void Promise.resolve(iterator.return?.()).catch(() => {
|
|
152
|
+
});
|
|
153
|
+
};
|
|
154
|
+
let stop;
|
|
155
|
+
const aborted = new Promise((resolve) => {
|
|
156
|
+
stop = () => resolve({ done: true, value: void 0 });
|
|
157
|
+
if (signal.aborted) stop();
|
|
158
|
+
else signal.addEventListener("abort", stop, { once: true });
|
|
159
|
+
});
|
|
160
|
+
let rows = [];
|
|
161
|
+
try {
|
|
162
|
+
for (; ; ) {
|
|
163
|
+
const step = await Promise.race([iterator.next(), aborted]);
|
|
164
|
+
if (signal.aborted) {
|
|
165
|
+
close();
|
|
166
|
+
return rows;
|
|
167
|
+
}
|
|
168
|
+
if (step.done) {
|
|
169
|
+
closed = true;
|
|
170
|
+
return rows;
|
|
171
|
+
}
|
|
172
|
+
rows = step.value;
|
|
173
|
+
onBatch(rows);
|
|
174
|
+
}
|
|
175
|
+
} catch (error) {
|
|
176
|
+
closed = true;
|
|
177
|
+
throw error;
|
|
178
|
+
} finally {
|
|
179
|
+
if (stop) signal.removeEventListener("abort", stop);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
141
182
|
export {
|
|
142
183
|
PALETTE_MODES,
|
|
143
184
|
absoluteHref,
|
|
@@ -154,5 +195,6 @@ export {
|
|
|
154
195
|
recentKey,
|
|
155
196
|
recentVisible,
|
|
156
197
|
resolveRecentItems,
|
|
198
|
+
settleFetched,
|
|
157
199
|
toRecentItem
|
|
158
200
|
};
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import type { ContextMenuItemDef } from "./LpContextMenu.vue";
|
|
2
|
+
import type { ToneName } from "./tone";
|
|
3
|
+
/**
|
|
4
|
+
* A button on a notification itself: "Approve", "Reply", "View invoice". The
|
|
5
|
+
* thing the notification asks for, done where it is read instead of a page away.
|
|
6
|
+
*/
|
|
7
|
+
export interface NotificationAction {
|
|
8
|
+
label: string;
|
|
9
|
+
/**
|
|
10
|
+
* `primary` is the one answer the notification is waiting for; `danger` a
|
|
11
|
+
* destructive one ("Decline", "Revoke"). Unset is a quiet secondary button.
|
|
12
|
+
*/
|
|
13
|
+
variant?: "primary" | "secondary" | "danger";
|
|
14
|
+
icon?: string;
|
|
15
|
+
/** A destination instead of a handler: the button is a link. */
|
|
16
|
+
href?: string;
|
|
17
|
+
/**
|
|
18
|
+
* Runs on press. A returned promise shows the button busy, and holds the
|
|
19
|
+
* row's other actions, until it settles; a rejection is left to the caller
|
|
20
|
+
* (toast it), and the row stays as it was.
|
|
21
|
+
*/
|
|
22
|
+
onSelect?: (item: NotificationItem) => unknown;
|
|
23
|
+
}
|
|
24
|
+
/** Who a notification is from, drawn as their avatar in place of the icon. */
|
|
25
|
+
export interface NotificationActor {
|
|
26
|
+
name: string;
|
|
27
|
+
/** Picture URL; the initials of `name` show without one. */
|
|
28
|
+
avatar?: string;
|
|
29
|
+
}
|
|
30
|
+
export interface NotificationItem {
|
|
31
|
+
id: string;
|
|
32
|
+
title: string;
|
|
33
|
+
body?: string;
|
|
34
|
+
/** Optional icon name (e.g. "lucide:check-circle"). With an `actor`, it is a small badge on the avatar. */
|
|
35
|
+
icon?: string;
|
|
36
|
+
/**
|
|
37
|
+
* Colours the row's icon by what KIND of notification it is — a billing
|
|
38
|
+
* notice and a security one should not look alike at a glance.
|
|
39
|
+
*
|
|
40
|
+
* A named tone rather than a class, so the categories stay themeable:
|
|
41
|
+
* consumers were mapping their own types onto raw palette classes, which is
|
|
42
|
+
* the one place a theme cannot follow them.
|
|
43
|
+
*/
|
|
44
|
+
tone?: ToneName;
|
|
45
|
+
/** Who it is from; the row leads with their avatar. */
|
|
46
|
+
actor?: NotificationActor;
|
|
47
|
+
/** Optional deep link; the row becomes a link when set. */
|
|
48
|
+
link?: string;
|
|
49
|
+
/** ISO-8601 creation time; rendered as a relative label and used for the day groups. */
|
|
50
|
+
createdAt?: string;
|
|
51
|
+
/** Whether the notification has been read. */
|
|
52
|
+
read?: boolean;
|
|
53
|
+
/** Buttons on the notification itself. See `NotificationAction`. */
|
|
54
|
+
actions?: NotificationAction[];
|
|
55
|
+
/**
|
|
56
|
+
* What became of it, once acted on ("Approved", "Declined by Anna"). Shown
|
|
57
|
+
* in place of the actions, so a handled request reads as handled.
|
|
58
|
+
*/
|
|
59
|
+
outcome?: string;
|
|
60
|
+
/** Which of the feed's `categories` tabs it belongs to. */
|
|
61
|
+
category?: string;
|
|
62
|
+
}
|
|
63
|
+
/** A tab of the feed beside All and Unread, keyed by `NotificationItem.category`. */
|
|
64
|
+
export interface NotificationCategory {
|
|
65
|
+
value: string;
|
|
66
|
+
label: string;
|
|
67
|
+
icon?: string;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Every user-facing string the feed and the bell render on their own. Apps
|
|
71
|
+
* with i18n pass their translations in (or set the `notifications` scope in
|
|
72
|
+
* the kit config); the English defaults keep the components usable bare.
|
|
73
|
+
*/
|
|
74
|
+
export interface NotificationLabels {
|
|
75
|
+
title?: string;
|
|
76
|
+
markAllRead?: string;
|
|
77
|
+
clear?: string;
|
|
78
|
+
markAsRead?: string;
|
|
79
|
+
markAsUnread?: string;
|
|
80
|
+
open?: string;
|
|
81
|
+
dismiss?: string;
|
|
82
|
+
empty?: string;
|
|
83
|
+
/** The Unread tab's empty state. */
|
|
84
|
+
emptyUnread?: string;
|
|
85
|
+
ariaLabel?: string;
|
|
86
|
+
/** Appended to the button's name while there is unread news; `{count}` is filled in. */
|
|
87
|
+
unread?: string;
|
|
88
|
+
/** Screen-reader marker on an unread row. */
|
|
89
|
+
unreadItem?: string;
|
|
90
|
+
/** Tabs. */
|
|
91
|
+
all?: string;
|
|
92
|
+
unreadTab?: string;
|
|
93
|
+
/** Day groups. */
|
|
94
|
+
today?: string;
|
|
95
|
+
yesterday?: string;
|
|
96
|
+
earlier?: string;
|
|
97
|
+
/** The header's settings button. */
|
|
98
|
+
settings?: string;
|
|
99
|
+
/** The footer link (`allLink`). */
|
|
100
|
+
viewAll?: string;
|
|
101
|
+
loadMore?: string;
|
|
102
|
+
/** Actions of a row, as a group. */
|
|
103
|
+
actions?: string;
|
|
104
|
+
/**
|
|
105
|
+
* No longer read: times are worded by Intl in the app's locale. Still
|
|
106
|
+
* accepted so existing label objects keep type-checking.
|
|
107
|
+
* @deprecated
|
|
108
|
+
*/
|
|
109
|
+
justNow?: string;
|
|
110
|
+
/** @deprecated See `justNow`. */
|
|
111
|
+
minutes?: string;
|
|
112
|
+
/** @deprecated See `justNow`. */
|
|
113
|
+
hours?: string;
|
|
114
|
+
/** @deprecated See `justNow`. */
|
|
115
|
+
days?: string;
|
|
116
|
+
}
|
|
117
|
+
export declare const NOTIFICATION_LABELS: {
|
|
118
|
+
title: string;
|
|
119
|
+
markAllRead: string;
|
|
120
|
+
clear: string;
|
|
121
|
+
markAsRead: string;
|
|
122
|
+
markAsUnread: string;
|
|
123
|
+
open: string;
|
|
124
|
+
dismiss: string;
|
|
125
|
+
empty: string;
|
|
126
|
+
emptyUnread: string;
|
|
127
|
+
ariaLabel: string;
|
|
128
|
+
unread: string;
|
|
129
|
+
unreadItem: string;
|
|
130
|
+
all: string;
|
|
131
|
+
unreadTab: string;
|
|
132
|
+
today: string;
|
|
133
|
+
yesterday: string;
|
|
134
|
+
earlier: string;
|
|
135
|
+
settings: string;
|
|
136
|
+
viewAll: string;
|
|
137
|
+
loadMore: string;
|
|
138
|
+
actions: string;
|
|
139
|
+
};
|
|
140
|
+
/** Extra right-click entries for a row, after the built-in ones. */
|
|
141
|
+
export type NotificationMenu = (item: NotificationItem) => ContextMenuItemDef[];
|
|
142
|
+
/** today | yesterday | earlier, in the viewer's own calendar. */
|
|
143
|
+
export declare function dayOf(iso: string | undefined, now: number): "today" | "yesterday" | "earlier";
|
|
144
|
+
export interface NotificationGroup {
|
|
145
|
+
key: string;
|
|
146
|
+
day: "today" | "yesterday" | "earlier" | null;
|
|
147
|
+
items: NotificationItem[];
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Runs of consecutive items from the same day. Consecutive, not sorted: the
|
|
151
|
+
* feed keeps the caller's order, and an out-of-order item opens a new run
|
|
152
|
+
* rather than being moved away from where the caller put it.
|
|
153
|
+
*/
|
|
154
|
+
export declare function groupByDay(items: NotificationItem[], now: number, grouped: boolean): NotificationGroup[];
|
|
155
|
+
/** The milliseconds until the next local midnight, when the day groups move. */
|
|
156
|
+
export declare function untilMidnight(now: number): number;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
const NOTIFICATION_LABELS = {
|
|
2
|
+
title: "Notifications",
|
|
3
|
+
markAllRead: "Mark all read",
|
|
4
|
+
clear: "Clear",
|
|
5
|
+
markAsRead: "Mark as read",
|
|
6
|
+
markAsUnread: "Mark as unread",
|
|
7
|
+
open: "Open",
|
|
8
|
+
dismiss: "Dismiss",
|
|
9
|
+
empty: "No notifications",
|
|
10
|
+
emptyUnread: "You're all caught up",
|
|
11
|
+
ariaLabel: "",
|
|
12
|
+
unread: "{count} unread",
|
|
13
|
+
unreadItem: "Unread",
|
|
14
|
+
all: "All",
|
|
15
|
+
unreadTab: "Unread",
|
|
16
|
+
today: "Today",
|
|
17
|
+
yesterday: "Yesterday",
|
|
18
|
+
earlier: "Earlier",
|
|
19
|
+
settings: "Notification settings",
|
|
20
|
+
viewAll: "View all notifications",
|
|
21
|
+
loadMore: "Load more",
|
|
22
|
+
actions: "Actions"
|
|
23
|
+
};
|
|
24
|
+
const DAY_MS = 864e5;
|
|
25
|
+
function dayStart(time) {
|
|
26
|
+
const d = new Date(time);
|
|
27
|
+
d.setHours(0, 0, 0, 0);
|
|
28
|
+
return d.getTime();
|
|
29
|
+
}
|
|
30
|
+
function dayOf(iso, now) {
|
|
31
|
+
const time = iso ? Date.parse(iso) : Number.NaN;
|
|
32
|
+
if (Number.isNaN(time)) return "earlier";
|
|
33
|
+
const today = dayStart(now);
|
|
34
|
+
if (time >= today) return "today";
|
|
35
|
+
if (time >= dayStart(today - DAY_MS / 2)) return "yesterday";
|
|
36
|
+
return "earlier";
|
|
37
|
+
}
|
|
38
|
+
function groupByDay(items, now, grouped) {
|
|
39
|
+
if (!grouped || !items.some((item) => item.createdAt)) return [{ key: "all", day: null, items }];
|
|
40
|
+
const groups = [];
|
|
41
|
+
for (const item of items) {
|
|
42
|
+
const day = dayOf(item.createdAt, now);
|
|
43
|
+
const last = groups.at(-1);
|
|
44
|
+
if (last?.day === day) last.items.push(item);
|
|
45
|
+
else groups.push({ key: `${day}-${groups.length}`, day, items: [item] });
|
|
46
|
+
}
|
|
47
|
+
return groups;
|
|
48
|
+
}
|
|
49
|
+
function untilMidnight(now) {
|
|
50
|
+
const next = new Date(now);
|
|
51
|
+
next.setHours(24, 0, 0, 0);
|
|
52
|
+
return Math.max(1e3, next.getTime() - now);
|
|
53
|
+
}
|
|
54
|
+
export {
|
|
55
|
+
NOTIFICATION_LABELS,
|
|
56
|
+
dayOf,
|
|
57
|
+
groupByDay,
|
|
58
|
+
untilMidnight
|
|
59
|
+
};
|
|
@@ -26,6 +26,11 @@ function formatterFor(locale, style) {
|
|
|
26
26
|
}
|
|
27
27
|
return f;
|
|
28
28
|
}
|
|
29
|
+
const SIGNED = /^[-+\u2212]/;
|
|
30
|
+
function say(fmt, locale, style, value, unit) {
|
|
31
|
+
const text = fmt.format(value, unit);
|
|
32
|
+
return style === "narrow" && SIGNED.test(text) ? formatterFor(locale, "short").format(value, unit) : text;
|
|
33
|
+
}
|
|
29
34
|
const MAX_REFRESH = HOUR;
|
|
30
35
|
const MIN_REFRESH = SECOND;
|
|
31
36
|
function formatRelativeTime(date, now = Date.now(), options = {}) {
|
|
@@ -47,7 +52,7 @@ function formatRelativeTime(date, now = Date.now(), options = {}) {
|
|
|
47
52
|
const boundary = diff < 0 ? (Math.floor(units + 0.5) + 0.5) * step.ms : (Math.ceil(units - 0.5) - 0.5) * step.ms;
|
|
48
53
|
const unitChange = diff < 0 ? step.until - abs : index > 0 ? abs - SCALE[index - 1].until : Infinity;
|
|
49
54
|
const refreshIn = Math.min(diff < 0 ? boundary - abs : abs - boundary, unitChange);
|
|
50
|
-
return { text: fmt
|
|
55
|
+
return { text: say(fmt, locale, style, value, step.unit), unit: step.unit, value, refreshIn: clampRefresh(refreshIn) };
|
|
51
56
|
}
|
|
52
57
|
function clampRefresh(ms) {
|
|
53
58
|
return clamp(Math.ceil(ms), MIN_REFRESH, MAX_REFRESH);
|
|
@@ -12,10 +12,15 @@
|
|
|
12
12
|
* and an error from a superseded run is dropped unseen. It is also one slot:
|
|
13
13
|
* a new `run` replaces the last, and `pending` speaks for the latest only, so
|
|
14
14
|
* independent requests each need their own `useAsyncTask`.
|
|
15
|
+
*
|
|
16
|
+
* A task that has something to show before it is done (the command palette's
|
|
17
|
+
* streamed results) calls `emit` with it: that reaches `apply` at once, for
|
|
18
|
+
* the latest run only, while `pending` stays true until the task settles. The
|
|
19
|
+
* value the task finally resolves to is applied as well, after the last emit.
|
|
15
20
|
*/
|
|
16
21
|
export declare function useAsyncTask<T>(): {
|
|
17
22
|
pending: import("vue").Ref<boolean, boolean>;
|
|
18
|
-
run: (task: (signal: AbortSignal) => T | Promise<T>, options: {
|
|
23
|
+
run: (task: (signal: AbortSignal, emit: (value: T) => void) => T | Promise<T>, options: {
|
|
19
24
|
delay?: number;
|
|
20
25
|
apply: (value: T) => void;
|
|
21
26
|
fail?: (error: unknown) => void;
|
|
@@ -19,7 +19,10 @@ function useAsyncTask() {
|
|
|
19
19
|
timer = setTimeout(async () => {
|
|
20
20
|
controller = new AbortController();
|
|
21
21
|
try {
|
|
22
|
-
const
|
|
22
|
+
const emit = (value2) => {
|
|
23
|
+
if (mine === token) options.apply(value2);
|
|
24
|
+
};
|
|
25
|
+
const value = await task(controller.signal, emit);
|
|
23
26
|
if (mine === token) options.apply(value);
|
|
24
27
|
} catch (error) {
|
|
25
28
|
if (mine === token) options.fail?.(error);
|
package/dist/icons-all.js
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -108,7 +108,8 @@ export { default as LpMediaGallery } from "./components/LpMediaGallery.vue";
|
|
|
108
108
|
export { default as LpModal } from "./components/LpModal.vue";
|
|
109
109
|
export { default as LpModalNav } from "./components/LpModalNav.vue";
|
|
110
110
|
export { default as LpNotificationBell } from "./components/LpNotificationBell.vue";
|
|
111
|
-
export
|
|
111
|
+
export { default as LpNotificationFeed } from "./components/LpNotificationFeed.vue";
|
|
112
|
+
export type { NotificationAction, NotificationActor, NotificationCategory, NotificationItem, NotificationLabels, NotificationMenu, } from "./components/notifications";
|
|
112
113
|
export { default as LpNumberField } from "./components/LpNumberField.vue";
|
|
113
114
|
export type { NumberFieldLabels } from "./components/LpNumberField.vue";
|
|
114
115
|
export { default as LpTimeField } from "./components/LpTimeField.vue";
|