@flamingo-stack/openframe-frontend-core 0.0.405 → 0.0.406-snapshot.20260711131925
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/{chunk-3KEBI6TP.cjs → chunk-2B6773QM.cjs} +1 -1
- package/dist/chunk-2B6773QM.cjs.map +1 -0
- package/dist/{chunk-RIGB7LP7.js → chunk-43H2WOAW.js} +3 -3
- package/dist/{chunk-QYTGHN2T.js → chunk-4UZH3MT2.js} +4 -4
- package/dist/{chunk-LREN3G7R.cjs → chunk-5M5W6XDY.cjs} +7 -7
- package/dist/{chunk-LREN3G7R.cjs.map → chunk-5M5W6XDY.cjs.map} +1 -1
- package/dist/{chunk-WEZIVLCO.cjs → chunk-74FWQI73.cjs} +18 -18
- package/dist/{chunk-WEZIVLCO.cjs.map → chunk-74FWQI73.cjs.map} +1 -1
- package/dist/{chunk-E6YHDT3D.js → chunk-7Q52HP45.js} +2 -2
- package/dist/chunk-7Q52HP45.js.map +1 -0
- package/dist/{chunk-3XCNFTFV.js → chunk-7XVFSGQA.js} +3 -3
- package/dist/{chunk-QAFRLO5N.cjs → chunk-CUN4CJUN.cjs} +10 -11
- package/dist/chunk-CUN4CJUN.cjs.map +1 -0
- package/dist/{chunk-ICJRSNBM.js → chunk-CVYSW33D.js} +199 -189
- package/dist/chunk-CVYSW33D.js.map +1 -0
- package/dist/{chunk-FOJRR647.cjs → chunk-DOBNDDNE.cjs} +75 -75
- package/dist/{chunk-FOJRR647.cjs.map → chunk-DOBNDDNE.cjs.map} +1 -1
- package/dist/{chunk-FFYEDIAG.cjs → chunk-GGDM5J4B.cjs} +332 -322
- package/dist/chunk-GGDM5J4B.cjs.map +1 -0
- package/dist/{chunk-UN2BJ7XW.js → chunk-GJSLKATJ.js} +2 -2
- package/dist/{chunk-GT7AJXKH.js → chunk-GMZL4T7C.js} +3 -3
- package/dist/{chunk-BK7QCB5J.js → chunk-H66L2265.js} +6 -6
- package/dist/{chunk-F3YLM5PO.js → chunk-HB63TQQO.js} +2 -2
- package/dist/{chunk-5XZEY34X.js → chunk-HJIRG7R6.js} +4 -4
- package/dist/{chunk-NA7XJRWB.js → chunk-KFQXO7QB.js} +1 -1
- package/dist/chunk-KFQXO7QB.js.map +1 -0
- package/dist/{chunk-Q2KKEE6W.js → chunk-KLBEIJVZ.js} +7 -7
- package/dist/{chunk-M6BGJVDY.cjs → chunk-LC6RRLFA.cjs} +15 -15
- package/dist/{chunk-M6BGJVDY.cjs.map → chunk-LC6RRLFA.cjs.map} +1 -1
- package/dist/{chunk-VFWEFR3Q.cjs → chunk-LPC3C7MG.cjs} +40 -40
- package/dist/{chunk-VFWEFR3Q.cjs.map → chunk-LPC3C7MG.cjs.map} +1 -1
- package/dist/{chunk-PNJ5LMVK.js → chunk-NO2KT42M.js} +9 -10
- package/dist/{chunk-PNJ5LMVK.js.map → chunk-NO2KT42M.js.map} +1 -1
- package/dist/{chunk-RC35ITSR.js → chunk-NSF7JUXF.js} +7 -7
- package/dist/{chunk-V4MOB3AD.cjs → chunk-PRKMOF2U.cjs} +14 -14
- package/dist/{chunk-V4MOB3AD.cjs.map → chunk-PRKMOF2U.cjs.map} +1 -1
- package/dist/{chunk-DHIYBC5Z.cjs → chunk-Q2MC3CBI.cjs} +35 -35
- package/dist/{chunk-DHIYBC5Z.cjs.map → chunk-Q2MC3CBI.cjs.map} +1 -1
- package/dist/{chunk-BS6O4HLJ.cjs → chunk-R4MXLJUS.cjs} +42 -42
- package/dist/{chunk-BS6O4HLJ.cjs.map → chunk-R4MXLJUS.cjs.map} +1 -1
- package/dist/{chunk-CCIBZ7TO.cjs → chunk-STGWQFYT.cjs} +5 -5
- package/dist/chunk-STGWQFYT.cjs.map +1 -0
- package/dist/{chunk-6OQ7YOX5.cjs → chunk-SY3QS2E5.cjs} +29 -29
- package/dist/{chunk-6OQ7YOX5.cjs.map → chunk-SY3QS2E5.cjs.map} +1 -1
- package/dist/{chunk-ELLTTMPE.cjs → chunk-WCPUJA3Y.cjs} +7 -7
- package/dist/{chunk-ELLTTMPE.cjs.map → chunk-WCPUJA3Y.cjs.map} +1 -1
- package/dist/{chunk-UIAQXIA6.js → chunk-XFP43YKG.js} +6 -6
- package/dist/{chunk-ACJ4CM6H.cjs → chunk-YX7C5JD7.cjs} +77 -77
- package/dist/{chunk-ACJ4CM6H.cjs.map → chunk-YX7C5JD7.cjs.map} +1 -1
- package/dist/components/announcement-bar.d.ts.map +1 -1
- package/dist/components/case-studies/index.cjs +10 -10
- package/dist/components/case-studies/index.js +4 -4
- package/dist/components/chat/index.cjs +4 -4
- package/dist/components/chat/index.js +3 -3
- package/dist/components/contact/index.cjs +5 -5
- package/dist/components/contact/index.js +4 -4
- package/dist/components/docs/index.cjs +7 -7
- package/dist/components/docs/index.js +6 -6
- package/dist/components/embeds/index.cjs +5 -5
- package/dist/components/embeds/index.js +4 -4
- package/dist/components/faq/index.cjs +6 -6
- package/dist/components/faq/index.js +5 -5
- package/dist/components/features/index.cjs +4 -4
- package/dist/components/features/index.js +3 -3
- package/dist/components/help-center-pages/index.cjs +23 -23
- package/dist/components/help-center-pages/index.js +14 -14
- package/dist/components/index.cjs +185 -179
- package/dist/components/index.cjs.map +1 -1
- package/dist/components/index.js +38 -32
- package/dist/components/index.js.map +1 -1
- package/dist/components/navigation/index.cjs +4 -4
- package/dist/components/navigation/index.js +3 -3
- package/dist/components/onboarding-guides/index.cjs +8 -8
- package/dist/components/onboarding-guides/index.js +7 -7
- package/dist/components/related-content/index.cjs +6 -6
- package/dist/components/related-content/index.js +5 -5
- package/dist/components/tickets/index.cjs +7 -7
- package/dist/components/tickets/index.js +6 -6
- package/dist/components/ui/index.cjs +4 -4
- package/dist/components/ui/index.js +3 -3
- package/dist/contexts/endpoints-runtime-context.d.ts +1 -1
- package/dist/contexts/endpoints-runtime-context.d.ts.map +1 -1
- package/dist/contexts/index.cjs +2 -2
- package/dist/contexts/index.js +1 -1
- package/dist/hooks/index.cjs +3 -3
- package/dist/hooks/index.js +2 -2
- package/dist/hooks/use-self-fetch.d.ts.map +1 -1
- package/dist/index.cjs +4 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +5 -5
- package/dist/types/announcement.cjs.map +1 -1
- package/dist/types/announcement.d.ts +0 -6
- package/dist/types/announcement.d.ts.map +1 -1
- package/dist/types/announcement.js.map +1 -1
- package/dist/types/index.cjs.map +1 -1
- package/dist/types/index.js.map +1 -1
- package/dist/utils/announcement-storage.d.ts +3 -0
- package/dist/utils/announcement-storage.d.ts.map +1 -1
- package/dist/utils/app-config.d.ts.map +1 -1
- package/dist/utils/color-analysis.d.ts +0 -4
- package/dist/utils/color-analysis.d.ts.map +1 -1
- package/dist/utils/index.cjs +186 -177
- package/dist/utils/index.cjs.map +1 -1
- package/dist/utils/index.js +185 -176
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/ods-color-utils.d.ts +2 -1
- package/dist/utils/ods-color-utils.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/components/announcement-bar.tsx +38 -21
- package/src/components/features/video.tsx +8 -0
- package/src/contexts/endpoints-runtime-context.tsx +1 -1
- package/src/hooks/use-self-fetch.ts +10 -9
- package/src/stories/AnnouncementBar.stories.tsx +8 -14
- package/src/types/announcement.ts +0 -8
- package/src/utils/announcement-storage.ts +17 -0
- package/src/utils/app-config.ts +3 -2
- package/src/utils/color-analysis.ts +5 -2
- package/src/utils/ods-color-utils.ts +4 -7
- package/dist/chunk-3KEBI6TP.cjs.map +0 -1
- package/dist/chunk-CCIBZ7TO.cjs.map +0 -1
- package/dist/chunk-E6YHDT3D.js.map +0 -1
- package/dist/chunk-FFYEDIAG.cjs.map +0 -1
- package/dist/chunk-ICJRSNBM.js.map +0 -1
- package/dist/chunk-NA7XJRWB.js.map +0 -1
- package/dist/chunk-QAFRLO5N.cjs.map +0 -1
- /package/dist/{chunk-RIGB7LP7.js.map → chunk-43H2WOAW.js.map} +0 -0
- /package/dist/{chunk-QYTGHN2T.js.map → chunk-4UZH3MT2.js.map} +0 -0
- /package/dist/{chunk-3XCNFTFV.js.map → chunk-7XVFSGQA.js.map} +0 -0
- /package/dist/{chunk-UN2BJ7XW.js.map → chunk-GJSLKATJ.js.map} +0 -0
- /package/dist/{chunk-GT7AJXKH.js.map → chunk-GMZL4T7C.js.map} +0 -0
- /package/dist/{chunk-BK7QCB5J.js.map → chunk-H66L2265.js.map} +0 -0
- /package/dist/{chunk-F3YLM5PO.js.map → chunk-HB63TQQO.js.map} +0 -0
- /package/dist/{chunk-5XZEY34X.js.map → chunk-HJIRG7R6.js.map} +0 -0
- /package/dist/{chunk-Q2KKEE6W.js.map → chunk-KLBEIJVZ.js.map} +0 -0
- /package/dist/{chunk-RC35ITSR.js.map → chunk-NSF7JUXF.js.map} +0 -0
- /package/dist/{chunk-UIAQXIA6.js.map → chunk-XFP43YKG.js.map} +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import {
|
|
3
3
|
useSelfFetch
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-NO2KT42M.js";
|
|
5
5
|
import {
|
|
6
6
|
BlogCard,
|
|
7
7
|
BlogCardSkeleton,
|
|
@@ -33,7 +33,7 @@ import {
|
|
|
33
33
|
getContentRefLabelOrTitleCase,
|
|
34
34
|
init_pagination,
|
|
35
35
|
orderContentRefTypes
|
|
36
|
-
} from "./chunk-
|
|
36
|
+
} from "./chunk-CVYSW33D.js";
|
|
37
37
|
|
|
38
38
|
// src/components/related-content/related-content-section.tsx
|
|
39
39
|
import { useEffect, useMemo, useRef, useState } from "react";
|
|
@@ -359,4 +359,4 @@ export {
|
|
|
359
359
|
GROUP_PAGE_SIZE,
|
|
360
360
|
RelatedContentSection
|
|
361
361
|
};
|
|
362
|
-
//# sourceMappingURL=chunk-
|
|
362
|
+
//# sourceMappingURL=chunk-7XVFSGQA.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }"use client";
|
|
2
2
|
|
|
3
3
|
|
|
4
|
-
var
|
|
4
|
+
var _chunkSTGWQFYTcjs = require('./chunk-STGWQFYT.cjs');
|
|
5
5
|
|
|
6
6
|
// src/hooks/use-self-fetch.ts
|
|
7
7
|
var _react = require('react');
|
|
@@ -29,7 +29,7 @@ function useSelfFetch(url, options) {
|
|
|
29
29
|
try {
|
|
30
30
|
setIsLoading(true);
|
|
31
31
|
setError(false);
|
|
32
|
-
const res = await
|
|
32
|
+
const res = await _chunkSTGWQFYTcjs.contentFetch.call(void 0, url, { signal: ctrl.signal });
|
|
33
33
|
if (!res.ok) throw new Error(`Request failed (${res.status})`);
|
|
34
34
|
const json = await res.json();
|
|
35
35
|
if (!cancelled) {
|
|
@@ -51,13 +51,16 @@ function useSelfFetch(url, options) {
|
|
|
51
51
|
ctrl.abort();
|
|
52
52
|
};
|
|
53
53
|
}, [url, reloadKey]);
|
|
54
|
+
const forceReload = () => {
|
|
55
|
+
dataUrlRef.current = null;
|
|
56
|
+
setReloadKey((k) => k + 1);
|
|
57
|
+
};
|
|
54
58
|
_react.useEffect.call(void 0, () => {
|
|
55
59
|
if (!revalidateOnVisibleAfterMs || url === null) return;
|
|
56
60
|
const onVisible = () => {
|
|
57
61
|
if (document.visibilityState !== "visible") return;
|
|
58
62
|
if (Date.now() - dataAtRef.current < revalidateOnVisibleAfterMs) return;
|
|
59
|
-
|
|
60
|
-
setReloadKey((k) => k + 1);
|
|
63
|
+
forceReload();
|
|
61
64
|
};
|
|
62
65
|
document.addEventListener("visibilitychange", onVisible);
|
|
63
66
|
return () => document.removeEventListener("visibilitychange", onVisible);
|
|
@@ -67,16 +70,12 @@ function useSelfFetch(url, options) {
|
|
|
67
70
|
setData,
|
|
68
71
|
isLoading,
|
|
69
72
|
error,
|
|
70
|
-
// Force a re-fetch of the current url
|
|
71
|
-
|
|
72
|
-
reload: () => {
|
|
73
|
-
dataUrlRef.current = null;
|
|
74
|
-
setReloadKey((k) => k + 1);
|
|
75
|
-
}
|
|
73
|
+
// Force a re-fetch of the current url (error-retry affordance).
|
|
74
|
+
reload: forceReload
|
|
76
75
|
};
|
|
77
76
|
}
|
|
78
77
|
|
|
79
78
|
|
|
80
79
|
|
|
81
80
|
exports.useSelfFetch = useSelfFetch;
|
|
82
|
-
//# sourceMappingURL=chunk-
|
|
81
|
+
//# sourceMappingURL=chunk-CUN4CJUN.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/home/runner/work/openframe-oss-lib/openframe-oss-lib/openframe-frontend-core/dist/chunk-CUN4CJUN.cjs","../src/hooks/use-self-fetch.ts"],"names":[],"mappings":"AAAA,6rBAAY;AACZ;AACE;AACF,wDAA6B;AAC7B;AACA;ACHA,8BAAgF;AAyCzE,SAAS,YAAA,CACd,GAAA,EACA,OAAA,EACuB;AACvB,EAAA,MAAM,YAAA,kBAAc,OAAA,2BAAS,aAAA;AAC7B,EAAA,MAAM,2BAAA,kBAA6B,OAAA,6BAAS,4BAAA;AAC5C,EAAA,MAAM,CAAC,IAAA,EAAM,OAAO,EAAA,EAAI,6BAAA,iBAAmB,WAAA,UAAe,MAAI,CAAA;AAC9D,EAAA,MAAM,CAAC,SAAA,EAAW,YAAY,EAAA,EAAI,6BAAA,YAAS,IAAgB,KAAA,EAAA,GAAa,IAAA,IAAQ,IAAI,CAAA;AACpF,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,EAAA,EAAI,6BAAA,KAAc,CAAA;AACxC,EAAA,MAAM,CAAC,SAAA,EAAW,YAAY,EAAA,EAAI,6BAAA,CAAU,CAAA;AAI5C,EAAA,MAAM,UAAA,EAAY,2BAAA,YAAe,IAAgB,KAAA,EAAA,EAAY,IAAA,CAAK,GAAA,CAAI,EAAA,EAAI,CAAC,CAAA;AAM3E,EAAA,MAAM,WAAA,EAAa,2BAAA,YAAsB,IAAgB,KAAA,EAAA,EAAY,IAAA,EAAM,IAAI,CAAA;AAK/E,EAAA,8BAAA,CAAU,EAAA,GAAM;AACd,IAAA,GAAA,CAAI,YAAA,IAAgB,KAAA,CAAA,EAAW,OAAA,CAAQ,WAAW,CAAA;AAAA,EACpD,CAAA,EAAG,CAAC,WAAW,CAAC,CAAA;AAEhB,EAAA,8BAAA,CAAU,EAAA,GAAM;AACd,IAAA,GAAA,CAAI,IAAA,IAAQ,IAAA,EAAM;AAChB,MAAA,YAAA,CAAa,KAAK,CAAA;AAClB,MAAA,MAAA;AAAA,IACF;AAGA,IAAA,GAAA,CAAI,UAAA,CAAW,QAAA,IAAY,GAAA,EAAK,MAAA;AAChC,IAAA,MAAM,KAAA,EAAO,IAAI,eAAA,CAAgB,CAAA;AACjC,IAAA,IAAI,UAAA,EAAY,KAAA;AAChB,IAAA,MAAA,SAAe,IAAA,CAAA,EAAO;AACpB,MAAA,IAAI;AACF,QAAA,YAAA,CAAa,IAAI,CAAA;AACjB,QAAA,QAAA,CAAS,KAAK,CAAA;AACd,QAAA,MAAM,IAAA,EAAM,MAAM,4CAAA,GAAa,EAAe,EAAE,MAAA,EAAQ,IAAA,CAAK,OAAO,CAAC,CAAA;AACrE,QAAA,GAAA,CAAI,CAAC,GAAA,CAAI,EAAA,EAAI,MAAM,IAAI,KAAA,CAAM,CAAA,gBAAA,EAAmB,GAAA,CAAI,MAAM,CAAA,CAAA,CAAG,CAAA;AAC7D,QAAA,MAAM,KAAA,EAAQ,MAAM,GAAA,CAAI,IAAA,CAAK,CAAA;AAC7B,QAAA,GAAA,CAAI,CAAC,SAAA,EAAW;AACd,UAAA,OAAA,CAAQ,IAAI,CAAA;AACZ,UAAA,UAAA,CAAW,QAAA,EAAU,GAAA;AACrB,UAAA,SAAA,CAAU,QAAA,EAAU,IAAA,CAAK,GAAA,CAAI,CAAA;AAAA,QAC/B;AAAA,MACF,EAAA,MAAA,CAAS,GAAA,EAAK;AAMZ,QAAA,GAAA,CAAI,UAAA,mBAAc,GAAA,6BAAe,OAAA,IAAS,YAAA,EAAc,MAAA;AACxD,QAAA,QAAA,CAAS,IAAI,CAAA;AACb,QAAA,OAAA,CAAQ,KAAA,CAAM,eAAA,EAAiB,GAAA,EAAK,GAAG,CAAA;AAAA,MACzC,EAAA,QAAE;AACA,QAAA,GAAA,CAAI,CAAC,SAAA,EAAW,YAAA,CAAa,KAAK,CAAA;AAAA,MACpC;AAAA,IACF;AACA,IAAA,IAAA,CAAK,CAAA;AACL,IAAA,OAAO,CAAA,EAAA,GAAM;AACX,MAAA,UAAA,EAAY,IAAA;AACZ,MAAA,IAAA,CAAK,KAAA,CAAM,CAAA;AAAA,IACb,CAAA;AAAA,EAEF,CAAA,EAAG,CAAC,GAAA,EAAK,SAAS,CAAC,CAAA;AAInB,EAAA,MAAM,YAAA,EAAc,CAAA,EAAA,GAAM;AACxB,IAAA,UAAA,CAAW,QAAA,EAAU,IAAA;AACrB,IAAA,YAAA,CAAa,CAAC,CAAA,EAAA,GAAM,EAAA,EAAI,CAAC,CAAA;AAAA,EAC3B,CAAA;AAKA,EAAA,8BAAA,CAAU,EAAA,GAAM;AACd,IAAA,GAAA,CAAI,CAAC,2BAAA,GAA8B,IAAA,IAAQ,IAAA,EAAM,MAAA;AACjD,IAAA,MAAM,UAAA,EAAY,CAAA,EAAA,GAAM;AACtB,MAAA,GAAA,CAAI,QAAA,CAAS,gBAAA,IAAoB,SAAA,EAAW,MAAA;AAC5C,MAAA,GAAA,CAAI,IAAA,CAAK,GAAA,CAAI,EAAA,EAAI,SAAA,CAAU,QAAA,EAAU,0BAAA,EAA4B,MAAA;AACjE,MAAA,WAAA,CAAY,CAAA;AAAA,IACd,CAAA;AACA,IAAA,QAAA,CAAS,gBAAA,CAAiB,kBAAA,EAAoB,SAAS,CAAA;AACvD,IAAA,OAAO,CAAA,EAAA,GAAM,QAAA,CAAS,mBAAA,CAAoB,kBAAA,EAAoB,SAAS,CAAA;AAAA,EACzE,CAAA,EAAG,CAAC,GAAA,EAAK,0BAA0B,CAAC,CAAA;AAEpC,EAAA,OAAO;AAAA,IACL,IAAA;AAAA,IACA,OAAA;AAAA,IACA,SAAA;AAAA,IACA,KAAA;AAAA;AAAA,IAEA,MAAA,EAAQ;AAAA,EACV,CAAA;AACF;ADnEA;AACA;AACE;AACF,oCAAC","file":"/home/runner/work/openframe-oss-lib/openframe-oss-lib/openframe-frontend-core/dist/chunk-CUN4CJUN.cjs","sourcesContent":[null,"'use client'\n\nimport { useEffect, useRef, useState, type Dispatch, type SetStateAction } from 'react'\nimport { contentFetch } from '../utils/embed-content-fetch'\n\nexport interface UseSelfFetchResult<T> {\n data: T | null\n /** Imperatively patch the fetched data (e.g. optimistic vote updates). */\n setData: Dispatch<SetStateAction<T | null>>\n isLoading: boolean\n error: boolean\n /** Re-run the fetch (error-retry affordance). */\n reload: () => void\n}\n\n/**\n * The single source for the 4 self-fetching content views\n * (`ProductReleasesView`, `RoadmapView`, the onboarding catalog/detail). GETs a\n * configured `url` into component state with **plain `fetch` + `useEffect`** —\n * deliberately NO react-query, so embedders don't need a QueryClient. This is\n * the same technology choice the shipped `DeliveryLists` makes; that component\n * predates this hook and still hand-rolls the loop (a future pass can migrate\n * it onto a two-url variant of this hook).\n *\n * Behaviour:\n * - `url = null` → fetching is DISABLED (controlled / SSR mode, or missing\n * config); returns `initialData ?? null` and never fetches.\n * - `initialData` provided → hydrates immediately and SKIPS the first fetch\n * (so the hub's server-rendered data isn't re-fetched on mount); later\n * `url` changes still re-fetch.\n * - a `cancelled` guard ensures an in-flight response from a STALE `url`\n * (e.g. a fast pagination / section toggle) can't overwrite a newer one.\n * - `reload()` bumps an internal key to retry after an error.\n * - `revalidateOnVisibleAfterMs` (opt-in) → re-fetch when the tab becomes\n * visible AND the held data is older than the threshold. Event-driven\n * freshness with ZERO background requests — the replacement for\n * setInterval polling. Data age counts from the last completed fetch, or\n * from mount when `initialData` seeded it (an SSR seed is milliseconds\n * old — without that, the first refocus would always refire).\n *\n * Re-fetches whenever `url` changes, so callers fold all query params INTO the\n * url string (the url IS the cache key).\n */\nexport function useSelfFetch<T>(\n url: string | null,\n options?: { initialData?: T; revalidateOnVisibleAfterMs?: number },\n): UseSelfFetchResult<T> {\n const initialData = options?.initialData\n const revalidateOnVisibleAfterMs = options?.revalidateOnVisibleAfterMs\n const [data, setData] = useState<T | null>(initialData ?? null)\n const [isLoading, setIsLoading] = useState(initialData === undefined && url !== null)\n const [error, setError] = useState(false)\n const [reloadKey, setReloadKey] = useState(0)\n // When the held data was obtained: seeded at mount for SSR-hydrated data,\n // stamped after each completed fetch. Drives the visibility revalidation age\n // check. 0 = nothing held yet (first visible event may fetch).\n const dataAtRef = useRef<number>(initialData !== undefined ? Date.now() : 0)\n // The url whose data we currently hold — seeded from SSR `initialData`, then set after\n // each completed fetch. The effect skips the fetch when this equals `url` (so server-\n // rendered data isn't re-fetched on mount). A VALUE compare (not a one-shot flag) so the\n // SSR-hydration skip survives React 18 StrictMode's mount→unmount→remount in dev;\n // `reload()` nulls it to force a re-fetch of the same url.\n const dataUrlRef = useRef<string | null>(initialData !== undefined ? url : null)\n\n // Re-sync when a CONTROLLED `initialData` changes (e.g. the host navigates\n // between detail slugs without remounting). No-op in self-fetch mode, where\n // `initialData` is `undefined`.\n useEffect(() => {\n if (initialData !== undefined) setData(initialData)\n }, [initialData])\n\n useEffect(() => {\n if (url === null) {\n setIsLoading(false)\n return\n }\n // Already hold data for this exact url (SSR-hydrated, or a prior completed fetch) →\n // skip. `reload()` clears `dataUrlRef` so a retry of the same url still fetches.\n if (dataUrlRef.current === url) return\n const ctrl = new AbortController()\n let cancelled = false\n async function load() {\n try {\n setIsLoading(true)\n setError(false)\n const res = await contentFetch(url as string, { signal: ctrl.signal })\n if (!res.ok) throw new Error(`Request failed (${res.status})`)\n const json = (await res.json()) as T\n if (!cancelled) {\n setData(json)\n dataUrlRef.current = url // remember the url we now hold data for\n dataAtRef.current = Date.now()\n }\n } catch (err) {\n // AbortError on cleanup (unmount / stale-url change / React StrictMode's dev\n // double-invoke) is EXPECTED — the request was intentionally aborted. Aborting\n // also means the orphaned StrictMode fetch shows as \"cancelled\" instead of\n // completing as a wasted duplicate (parity with useChatIdentity). Only real\n // failures fall through to the error state + console.\n if (cancelled || (err as Error)?.name === 'AbortError') return\n setError(true)\n console.error('useSelfFetch:', url, err)\n } finally {\n if (!cancelled) setIsLoading(false)\n }\n }\n load()\n return () => {\n cancelled = true\n ctrl.abort()\n }\n // `url` folds in every query param; `reloadKey` drives retry.\n }, [url, reloadKey])\n\n // ONE force-refetch mechanic shared by reload() and the visibility\n // revalidation: clear the held-url skip, bump the effect key.\n const forceReload = () => {\n dataUrlRef.current = null\n setReloadKey((k) => k + 1)\n }\n\n // Opt-in visibility-driven revalidation. Registered only when the option is\n // set and fetching is enabled; SSR-safe (effects don't run on the server)\n // and StrictMode-safe (idempotent listener, cleaned up per mount cycle).\n useEffect(() => {\n if (!revalidateOnVisibleAfterMs || url === null) return\n const onVisible = () => {\n if (document.visibilityState !== 'visible') return\n if (Date.now() - dataAtRef.current < revalidateOnVisibleAfterMs) return\n forceReload()\n }\n document.addEventListener('visibilitychange', onVisible)\n return () => document.removeEventListener('visibilitychange', onVisible)\n }, [url, revalidateOnVisibleAfterMs])\n\n return {\n data,\n setData,\n isLoading,\n error,\n // Force a re-fetch of the current url (error-retry affordance).\n reload: forceReload,\n }\n}\n"]}
|
|
@@ -26,7 +26,7 @@ import {
|
|
|
26
26
|
useOgPlaceholderUrl,
|
|
27
27
|
useOnboardingState,
|
|
28
28
|
useToast
|
|
29
|
-
} from "./chunk-
|
|
29
|
+
} from "./chunk-7Q52HP45.js";
|
|
30
30
|
import {
|
|
31
31
|
AlertCircleIcon,
|
|
32
32
|
AnthropicLogoGreyIcon,
|
|
@@ -150,7 +150,7 @@ import {
|
|
|
150
150
|
import {
|
|
151
151
|
useChatRuntime,
|
|
152
152
|
useRequiredChatRuntime
|
|
153
|
-
} from "./chunk-
|
|
153
|
+
} from "./chunk-KFQXO7QB.js";
|
|
154
154
|
import {
|
|
155
155
|
dynamic
|
|
156
156
|
} from "./chunk-EL5YVPD5.js";
|
|
@@ -2745,6 +2745,174 @@ function ColorSwatch({ color, className }) {
|
|
|
2745
2745
|
// src/components/ui/ticket-status-tag.tsx
|
|
2746
2746
|
init_cn();
|
|
2747
2747
|
|
|
2748
|
+
// src/utils/color-analysis.ts
|
|
2749
|
+
var DESIGN_PALETTE = [
|
|
2750
|
+
{ name: "yellow", hex: "#FFC008", rgb: [255, 192, 8] },
|
|
2751
|
+
{ name: "black", hex: "#161616", rgb: [22, 22, 22] },
|
|
2752
|
+
{ name: "gray", hex: "#888888", rgb: [136, 136, 136] }
|
|
2753
|
+
];
|
|
2754
|
+
function hexToRgb(hex) {
|
|
2755
|
+
const normalized = hex.replace(/^#?([a-f\d])([a-f\d])([a-f\d])$/i, (_, r, g, b) => `${r}${r}${g}${g}${b}${b}`);
|
|
2756
|
+
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(normalized);
|
|
2757
|
+
return result ? [parseInt(result[1], 16), parseInt(result[2], 16), parseInt(result[3], 16)] : [0, 0, 0];
|
|
2758
|
+
}
|
|
2759
|
+
function getLuminance(rgb) {
|
|
2760
|
+
const [r, g, b] = rgb.map((c) => {
|
|
2761
|
+
c = c / 255;
|
|
2762
|
+
return c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);
|
|
2763
|
+
});
|
|
2764
|
+
return 0.2126 * r + 0.7152 * g + 0.0722 * b;
|
|
2765
|
+
}
|
|
2766
|
+
function getContrastRatio(color1, color2) {
|
|
2767
|
+
const lum1 = getLuminance(color1);
|
|
2768
|
+
const lum2 = getLuminance(color2);
|
|
2769
|
+
const brightest = Math.max(lum1, lum2);
|
|
2770
|
+
const darkest = Math.min(lum1, lum2);
|
|
2771
|
+
return (brightest + 0.05) / (darkest + 0.05);
|
|
2772
|
+
}
|
|
2773
|
+
function pickReadableTextColor(bgHex) {
|
|
2774
|
+
const bg = hexToRgb(bgHex);
|
|
2775
|
+
const darkContrast = getContrastRatio(bg, [26, 26, 26]);
|
|
2776
|
+
const lightContrast = getContrastRatio(bg, [250, 250, 250]);
|
|
2777
|
+
return darkContrast >= lightContrast ? "dark" : "light";
|
|
2778
|
+
}
|
|
2779
|
+
function extractDominantColor(canvas) {
|
|
2780
|
+
const ctx = canvas.getContext("2d");
|
|
2781
|
+
if (!ctx) return [128, 128, 128];
|
|
2782
|
+
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
|
|
2783
|
+
const data = imageData.data;
|
|
2784
|
+
const sampleSize = Math.max(1, Math.floor(data.length / (4 * 1e3)));
|
|
2785
|
+
const colorCounts = {};
|
|
2786
|
+
for (let i = 0; i < data.length; i += 4 * sampleSize) {
|
|
2787
|
+
const r = data[i];
|
|
2788
|
+
const g = data[i + 1];
|
|
2789
|
+
const b = data[i + 2];
|
|
2790
|
+
const alpha = data[i + 3];
|
|
2791
|
+
if (alpha < 128) continue;
|
|
2792
|
+
const bucketR = Math.round(r / 32) * 32;
|
|
2793
|
+
const bucketG = Math.round(g / 32) * 32;
|
|
2794
|
+
const bucketB = Math.round(b / 32) * 32;
|
|
2795
|
+
const key = `${bucketR},${bucketG},${bucketB}`;
|
|
2796
|
+
colorCounts[key] = (colorCounts[key] || 0) + 1;
|
|
2797
|
+
}
|
|
2798
|
+
let maxCount = 0;
|
|
2799
|
+
let dominantColor = [128, 128, 128];
|
|
2800
|
+
for (const [colorKey, count] of Object.entries(colorCounts)) {
|
|
2801
|
+
if (count > maxCount) {
|
|
2802
|
+
maxCount = count;
|
|
2803
|
+
const [r, g, b] = colorKey.split(",").map(Number);
|
|
2804
|
+
dominantColor = [r, g, b];
|
|
2805
|
+
}
|
|
2806
|
+
}
|
|
2807
|
+
return dominantColor;
|
|
2808
|
+
}
|
|
2809
|
+
function getBestContrastColor(imageColor) {
|
|
2810
|
+
let bestColor = DESIGN_PALETTE[0];
|
|
2811
|
+
let bestContrast = 0;
|
|
2812
|
+
for (const color of DESIGN_PALETTE) {
|
|
2813
|
+
const contrast = getContrastRatio(imageColor, color.rgb);
|
|
2814
|
+
if (contrast > bestContrast) {
|
|
2815
|
+
bestContrast = contrast;
|
|
2816
|
+
bestColor = color;
|
|
2817
|
+
}
|
|
2818
|
+
}
|
|
2819
|
+
return bestContrast >= 3 ? bestColor : DESIGN_PALETTE.find((c) => c.name === "black") || bestColor;
|
|
2820
|
+
}
|
|
2821
|
+
function analyzeImageColor(imageSrc) {
|
|
2822
|
+
return new Promise((resolve, reject) => {
|
|
2823
|
+
const img = new Image();
|
|
2824
|
+
img.crossOrigin = "anonymous";
|
|
2825
|
+
img.onload = () => {
|
|
2826
|
+
try {
|
|
2827
|
+
const canvas = document.createElement("canvas");
|
|
2828
|
+
const ctx = canvas.getContext("2d");
|
|
2829
|
+
if (!ctx) {
|
|
2830
|
+
reject(new Error("Could not get canvas context"));
|
|
2831
|
+
return;
|
|
2832
|
+
}
|
|
2833
|
+
const maxSize = 100;
|
|
2834
|
+
const scale = Math.min(maxSize / img.width, maxSize / img.height);
|
|
2835
|
+
canvas.width = img.width * scale;
|
|
2836
|
+
canvas.height = img.height * scale;
|
|
2837
|
+
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
|
|
2838
|
+
const dominantColor = extractDominantColor(canvas);
|
|
2839
|
+
const bestContrastColor = getBestContrastColor(dominantColor);
|
|
2840
|
+
resolve(bestContrastColor);
|
|
2841
|
+
} catch (error) {
|
|
2842
|
+
reject(error);
|
|
2843
|
+
}
|
|
2844
|
+
};
|
|
2845
|
+
img.onerror = () => reject(new Error("Failed to load image"));
|
|
2846
|
+
img.src = imageSrc;
|
|
2847
|
+
});
|
|
2848
|
+
}
|
|
2849
|
+
async function extractImageEdgeColorAsync(imageUrl) {
|
|
2850
|
+
return new Promise((resolve) => {
|
|
2851
|
+
if (typeof window === "undefined") {
|
|
2852
|
+
resolve("#000000");
|
|
2853
|
+
return;
|
|
2854
|
+
}
|
|
2855
|
+
const img = new Image();
|
|
2856
|
+
img.crossOrigin = "anonymous";
|
|
2857
|
+
img.onload = () => {
|
|
2858
|
+
try {
|
|
2859
|
+
const canvas = document.createElement("canvas");
|
|
2860
|
+
const ctx = canvas.getContext("2d");
|
|
2861
|
+
if (!ctx) {
|
|
2862
|
+
resolve("#000000");
|
|
2863
|
+
return;
|
|
2864
|
+
}
|
|
2865
|
+
const maxSize = 50;
|
|
2866
|
+
const scale = Math.min(maxSize / img.naturalWidth, maxSize / img.naturalHeight);
|
|
2867
|
+
const w = Math.round(img.naturalWidth * scale);
|
|
2868
|
+
const h = Math.round(img.naturalHeight * scale);
|
|
2869
|
+
canvas.width = w;
|
|
2870
|
+
canvas.height = h;
|
|
2871
|
+
ctx.drawImage(img, 0, 0, w, h);
|
|
2872
|
+
const data = ctx.getImageData(0, 0, w, h).data;
|
|
2873
|
+
const edgeW = Math.max(2, Math.round(w * 0.15));
|
|
2874
|
+
const edgeH = Math.max(2, Math.round(h * 0.15));
|
|
2875
|
+
const bucketSize = 32;
|
|
2876
|
+
const buckets = /* @__PURE__ */ new Map();
|
|
2877
|
+
for (let y = 0; y < h; y++) {
|
|
2878
|
+
for (let x = 0; x < w; x++) {
|
|
2879
|
+
if (!(x < edgeW || x >= w - edgeW || y < edgeH || y >= h - edgeH)) continue;
|
|
2880
|
+
const i = (y * w + x) * 4;
|
|
2881
|
+
if (data[i + 3] < 128) continue;
|
|
2882
|
+
const br = Math.floor(data[i] / bucketSize) * bucketSize;
|
|
2883
|
+
const bg = Math.floor(data[i + 1] / bucketSize) * bucketSize;
|
|
2884
|
+
const bb = Math.floor(data[i + 2] / bucketSize) * bucketSize;
|
|
2885
|
+
const key = `${br},${bg},${bb}`;
|
|
2886
|
+
const existing = buckets.get(key);
|
|
2887
|
+
if (existing) {
|
|
2888
|
+
existing.r += data[i];
|
|
2889
|
+
existing.g += data[i + 1];
|
|
2890
|
+
existing.b += data[i + 2];
|
|
2891
|
+
existing.count++;
|
|
2892
|
+
} else {
|
|
2893
|
+
buckets.set(key, { r: data[i], g: data[i + 1], b: data[i + 2], count: 1 });
|
|
2894
|
+
}
|
|
2895
|
+
}
|
|
2896
|
+
}
|
|
2897
|
+
let best = { r: 0, g: 0, b: 0, count: 0 };
|
|
2898
|
+
for (const b2 of buckets.values()) {
|
|
2899
|
+
if (b2.count > best.count) best = b2;
|
|
2900
|
+
}
|
|
2901
|
+
if (best.count === 0) {
|
|
2902
|
+
resolve("#000000");
|
|
2903
|
+
return;
|
|
2904
|
+
}
|
|
2905
|
+
const r = Math.round(best.r / best.count), g = Math.round(best.g / best.count), b = Math.round(best.b / best.count);
|
|
2906
|
+
resolve(`#${r.toString(16).padStart(2, "0")}${g.toString(16).padStart(2, "0")}${b.toString(16).padStart(2, "0")}`);
|
|
2907
|
+
} catch {
|
|
2908
|
+
resolve("#000000");
|
|
2909
|
+
}
|
|
2910
|
+
};
|
|
2911
|
+
img.onerror = () => resolve("#000000");
|
|
2912
|
+
img.src = imageUrl;
|
|
2913
|
+
});
|
|
2914
|
+
}
|
|
2915
|
+
|
|
2748
2916
|
// src/utils/ods-color-utils.ts
|
|
2749
2917
|
function getPlatformAccentColor(platform) {
|
|
2750
2918
|
const currentPlatform = platform || getCurrentPlatform();
|
|
@@ -2769,18 +2937,13 @@ function getCurrentPlatform() {
|
|
|
2769
2937
|
return process.env.NEXT_PUBLIC_APP_TYPE || "openmsp";
|
|
2770
2938
|
}
|
|
2771
2939
|
function getReadableTextColor(hex) {
|
|
2772
|
-
|
|
2773
|
-
const r = n >> 16 & 255;
|
|
2774
|
-
const g = n >> 8 & 255;
|
|
2775
|
-
const b = n & 255;
|
|
2776
|
-
const luminance = (0.299 * r + 0.587 * g + 0.114 * b) / 255;
|
|
2777
|
-
return luminance > 0.5 ? "#212121" : "#fafafa";
|
|
2940
|
+
return pickReadableTextColor(hex) === "dark" ? "#212121" : "#fafafa";
|
|
2778
2941
|
}
|
|
2779
2942
|
var HEX_PATTERN = /^#[0-9a-fA-F]{6}$/;
|
|
2780
2943
|
function clamp(n, min, max) {
|
|
2781
2944
|
return Math.max(min, Math.min(max, n));
|
|
2782
2945
|
}
|
|
2783
|
-
function
|
|
2946
|
+
function hexToRgb2(hex) {
|
|
2784
2947
|
if (!HEX_PATTERN.test(hex)) return null;
|
|
2785
2948
|
const n = Number.parseInt(hex.slice(1), 16);
|
|
2786
2949
|
return { r: n >> 16 & 255, g: n >> 8 & 255, b: n & 255 };
|
|
@@ -2792,7 +2955,7 @@ function rgbToHex(r, g, b) {
|
|
|
2792
2955
|
var HOVER_DARKEN_STEP = 10;
|
|
2793
2956
|
var ACTIVE_DARKEN_STEP = 20;
|
|
2794
2957
|
function darkenByStep(hex, step) {
|
|
2795
|
-
const rgb =
|
|
2958
|
+
const rgb = hexToRgb2(hex);
|
|
2796
2959
|
if (!rgb) return hex;
|
|
2797
2960
|
return rgbToHex(rgb.r - step, rgb.g - step, rgb.b - step);
|
|
2798
2961
|
}
|
|
@@ -10213,6 +10376,7 @@ function YouTubeFacadeInner({
|
|
|
10213
10376
|
src: embedUrl,
|
|
10214
10377
|
allow: "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share",
|
|
10215
10378
|
allowFullScreen: true,
|
|
10379
|
+
referrerPolicy: "strict-origin-when-cross-origin",
|
|
10216
10380
|
title,
|
|
10217
10381
|
className: "absolute inset-0 w-full h-full border-0 rounded-lg"
|
|
10218
10382
|
}
|
|
@@ -22900,173 +23064,6 @@ function isGenericWebsiteDomain(website) {
|
|
|
22900
23064
|
return isGenericDomain(normalizeDomain(website));
|
|
22901
23065
|
}
|
|
22902
23066
|
|
|
22903
|
-
// src/utils/color-analysis.ts
|
|
22904
|
-
var DESIGN_PALETTE = [
|
|
22905
|
-
{ name: "yellow", hex: "#FFC008", rgb: [255, 192, 8] },
|
|
22906
|
-
{ name: "black", hex: "#161616", rgb: [22, 22, 22] },
|
|
22907
|
-
{ name: "gray", hex: "#888888", rgb: [136, 136, 136] }
|
|
22908
|
-
];
|
|
22909
|
-
function hexToRgb2(hex) {
|
|
22910
|
-
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
|
|
22911
|
-
return result ? [parseInt(result[1], 16), parseInt(result[2], 16), parseInt(result[3], 16)] : [0, 0, 0];
|
|
22912
|
-
}
|
|
22913
|
-
function getLuminance(rgb) {
|
|
22914
|
-
const [r, g, b] = rgb.map((c) => {
|
|
22915
|
-
c = c / 255;
|
|
22916
|
-
return c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);
|
|
22917
|
-
});
|
|
22918
|
-
return 0.2126 * r + 0.7152 * g + 0.0722 * b;
|
|
22919
|
-
}
|
|
22920
|
-
function getContrastRatio(color1, color2) {
|
|
22921
|
-
const lum1 = getLuminance(color1);
|
|
22922
|
-
const lum2 = getLuminance(color2);
|
|
22923
|
-
const brightest = Math.max(lum1, lum2);
|
|
22924
|
-
const darkest = Math.min(lum1, lum2);
|
|
22925
|
-
return (brightest + 0.05) / (darkest + 0.05);
|
|
22926
|
-
}
|
|
22927
|
-
function pickReadableTextColor(bgHex) {
|
|
22928
|
-
const bg = hexToRgb2(bgHex);
|
|
22929
|
-
const darkContrast = getContrastRatio(bg, [26, 26, 26]);
|
|
22930
|
-
const lightContrast = getContrastRatio(bg, [250, 250, 250]);
|
|
22931
|
-
return darkContrast >= lightContrast ? "dark" : "light";
|
|
22932
|
-
}
|
|
22933
|
-
function extractDominantColor(canvas) {
|
|
22934
|
-
const ctx = canvas.getContext("2d");
|
|
22935
|
-
if (!ctx) return [128, 128, 128];
|
|
22936
|
-
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
|
|
22937
|
-
const data = imageData.data;
|
|
22938
|
-
const sampleSize = Math.max(1, Math.floor(data.length / (4 * 1e3)));
|
|
22939
|
-
const colorCounts = {};
|
|
22940
|
-
for (let i = 0; i < data.length; i += 4 * sampleSize) {
|
|
22941
|
-
const r = data[i];
|
|
22942
|
-
const g = data[i + 1];
|
|
22943
|
-
const b = data[i + 2];
|
|
22944
|
-
const alpha = data[i + 3];
|
|
22945
|
-
if (alpha < 128) continue;
|
|
22946
|
-
const bucketR = Math.round(r / 32) * 32;
|
|
22947
|
-
const bucketG = Math.round(g / 32) * 32;
|
|
22948
|
-
const bucketB = Math.round(b / 32) * 32;
|
|
22949
|
-
const key = `${bucketR},${bucketG},${bucketB}`;
|
|
22950
|
-
colorCounts[key] = (colorCounts[key] || 0) + 1;
|
|
22951
|
-
}
|
|
22952
|
-
let maxCount = 0;
|
|
22953
|
-
let dominantColor = [128, 128, 128];
|
|
22954
|
-
for (const [colorKey, count] of Object.entries(colorCounts)) {
|
|
22955
|
-
if (count > maxCount) {
|
|
22956
|
-
maxCount = count;
|
|
22957
|
-
const [r, g, b] = colorKey.split(",").map(Number);
|
|
22958
|
-
dominantColor = [r, g, b];
|
|
22959
|
-
}
|
|
22960
|
-
}
|
|
22961
|
-
return dominantColor;
|
|
22962
|
-
}
|
|
22963
|
-
function getBestContrastColor(imageColor) {
|
|
22964
|
-
let bestColor = DESIGN_PALETTE[0];
|
|
22965
|
-
let bestContrast = 0;
|
|
22966
|
-
for (const color of DESIGN_PALETTE) {
|
|
22967
|
-
const contrast = getContrastRatio(imageColor, color.rgb);
|
|
22968
|
-
if (contrast > bestContrast) {
|
|
22969
|
-
bestContrast = contrast;
|
|
22970
|
-
bestColor = color;
|
|
22971
|
-
}
|
|
22972
|
-
}
|
|
22973
|
-
return bestContrast >= 3 ? bestColor : DESIGN_PALETTE.find((c) => c.name === "black") || bestColor;
|
|
22974
|
-
}
|
|
22975
|
-
function analyzeImageColor(imageSrc) {
|
|
22976
|
-
return new Promise((resolve, reject) => {
|
|
22977
|
-
const img = new Image();
|
|
22978
|
-
img.crossOrigin = "anonymous";
|
|
22979
|
-
img.onload = () => {
|
|
22980
|
-
try {
|
|
22981
|
-
const canvas = document.createElement("canvas");
|
|
22982
|
-
const ctx = canvas.getContext("2d");
|
|
22983
|
-
if (!ctx) {
|
|
22984
|
-
reject(new Error("Could not get canvas context"));
|
|
22985
|
-
return;
|
|
22986
|
-
}
|
|
22987
|
-
const maxSize = 100;
|
|
22988
|
-
const scale = Math.min(maxSize / img.width, maxSize / img.height);
|
|
22989
|
-
canvas.width = img.width * scale;
|
|
22990
|
-
canvas.height = img.height * scale;
|
|
22991
|
-
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
|
|
22992
|
-
const dominantColor = extractDominantColor(canvas);
|
|
22993
|
-
const bestContrastColor = getBestContrastColor(dominantColor);
|
|
22994
|
-
resolve(bestContrastColor);
|
|
22995
|
-
} catch (error) {
|
|
22996
|
-
reject(error);
|
|
22997
|
-
}
|
|
22998
|
-
};
|
|
22999
|
-
img.onerror = () => reject(new Error("Failed to load image"));
|
|
23000
|
-
img.src = imageSrc;
|
|
23001
|
-
});
|
|
23002
|
-
}
|
|
23003
|
-
async function extractImageEdgeColorAsync(imageUrl) {
|
|
23004
|
-
return new Promise((resolve) => {
|
|
23005
|
-
if (typeof window === "undefined") {
|
|
23006
|
-
resolve("#000000");
|
|
23007
|
-
return;
|
|
23008
|
-
}
|
|
23009
|
-
const img = new Image();
|
|
23010
|
-
img.crossOrigin = "anonymous";
|
|
23011
|
-
img.onload = () => {
|
|
23012
|
-
try {
|
|
23013
|
-
const canvas = document.createElement("canvas");
|
|
23014
|
-
const ctx = canvas.getContext("2d");
|
|
23015
|
-
if (!ctx) {
|
|
23016
|
-
resolve("#000000");
|
|
23017
|
-
return;
|
|
23018
|
-
}
|
|
23019
|
-
const maxSize = 50;
|
|
23020
|
-
const scale = Math.min(maxSize / img.naturalWidth, maxSize / img.naturalHeight);
|
|
23021
|
-
const w = Math.round(img.naturalWidth * scale);
|
|
23022
|
-
const h = Math.round(img.naturalHeight * scale);
|
|
23023
|
-
canvas.width = w;
|
|
23024
|
-
canvas.height = h;
|
|
23025
|
-
ctx.drawImage(img, 0, 0, w, h);
|
|
23026
|
-
const data = ctx.getImageData(0, 0, w, h).data;
|
|
23027
|
-
const edgeW = Math.max(2, Math.round(w * 0.15));
|
|
23028
|
-
const edgeH = Math.max(2, Math.round(h * 0.15));
|
|
23029
|
-
const bucketSize = 32;
|
|
23030
|
-
const buckets = /* @__PURE__ */ new Map();
|
|
23031
|
-
for (let y = 0; y < h; y++) {
|
|
23032
|
-
for (let x = 0; x < w; x++) {
|
|
23033
|
-
if (!(x < edgeW || x >= w - edgeW || y < edgeH || y >= h - edgeH)) continue;
|
|
23034
|
-
const i = (y * w + x) * 4;
|
|
23035
|
-
if (data[i + 3] < 128) continue;
|
|
23036
|
-
const br = Math.floor(data[i] / bucketSize) * bucketSize;
|
|
23037
|
-
const bg = Math.floor(data[i + 1] / bucketSize) * bucketSize;
|
|
23038
|
-
const bb = Math.floor(data[i + 2] / bucketSize) * bucketSize;
|
|
23039
|
-
const key = `${br},${bg},${bb}`;
|
|
23040
|
-
const existing = buckets.get(key);
|
|
23041
|
-
if (existing) {
|
|
23042
|
-
existing.r += data[i];
|
|
23043
|
-
existing.g += data[i + 1];
|
|
23044
|
-
existing.b += data[i + 2];
|
|
23045
|
-
existing.count++;
|
|
23046
|
-
} else {
|
|
23047
|
-
buckets.set(key, { r: data[i], g: data[i + 1], b: data[i + 2], count: 1 });
|
|
23048
|
-
}
|
|
23049
|
-
}
|
|
23050
|
-
}
|
|
23051
|
-
let best = { r: 0, g: 0, b: 0, count: 0 };
|
|
23052
|
-
for (const b2 of buckets.values()) {
|
|
23053
|
-
if (b2.count > best.count) best = b2;
|
|
23054
|
-
}
|
|
23055
|
-
if (best.count === 0) {
|
|
23056
|
-
resolve("#000000");
|
|
23057
|
-
return;
|
|
23058
|
-
}
|
|
23059
|
-
const r = Math.round(best.r / best.count), g = Math.round(best.g / best.count), b = Math.round(best.b / best.count);
|
|
23060
|
-
resolve(`#${r.toString(16).padStart(2, "0")}${g.toString(16).padStart(2, "0")}${b.toString(16).padStart(2, "0")}`);
|
|
23061
|
-
} catch {
|
|
23062
|
-
resolve("#000000");
|
|
23063
|
-
}
|
|
23064
|
-
};
|
|
23065
|
-
img.onerror = () => resolve("#000000");
|
|
23066
|
-
img.src = imageUrl;
|
|
23067
|
-
});
|
|
23068
|
-
}
|
|
23069
|
-
|
|
23070
23067
|
// src/utils/announcement-storage.ts
|
|
23071
23068
|
function announcementDismissCookieName(platform) {
|
|
23072
23069
|
return `${platform}-announcement-dismissed`;
|
|
@@ -23095,6 +23092,19 @@ function isAnnouncementDismissed(platform, id) {
|
|
|
23095
23092
|
return false;
|
|
23096
23093
|
}
|
|
23097
23094
|
}
|
|
23095
|
+
function clearAnnouncementDismissals(platform) {
|
|
23096
|
+
if (typeof document === "undefined") return;
|
|
23097
|
+
document.cookie = `${announcementDismissCookieName(platform)}=; path=/; max-age=0`;
|
|
23098
|
+
try {
|
|
23099
|
+
const prefix = `${platform}-announcement-`;
|
|
23100
|
+
Object.keys(localStorage).forEach((key) => {
|
|
23101
|
+
if (key.startsWith(prefix) && key.endsWith("-dismissed")) {
|
|
23102
|
+
localStorage.removeItem(key);
|
|
23103
|
+
}
|
|
23104
|
+
});
|
|
23105
|
+
} catch {
|
|
23106
|
+
}
|
|
23107
|
+
}
|
|
23098
23108
|
function clearLegacyAnnouncementCache(platform) {
|
|
23099
23109
|
if (typeof window === "undefined") return;
|
|
23100
23110
|
try {
|
|
@@ -41857,7 +41867,7 @@ function ChannelInput({
|
|
|
41857
41867
|
);
|
|
41858
41868
|
}
|
|
41859
41869
|
function RgbInputs({ value, onChange }) {
|
|
41860
|
-
const rgb =
|
|
41870
|
+
const rgb = hexToRgb2(value) ?? { r: 0, g: 0, b: 0 };
|
|
41861
41871
|
const update = (next) => {
|
|
41862
41872
|
const r = next.r ?? rgb.r;
|
|
41863
41873
|
const g = next.g ?? rgb.g;
|
|
@@ -41871,7 +41881,7 @@ function RgbInputs({ value, onChange }) {
|
|
|
41871
41881
|
] });
|
|
41872
41882
|
}
|
|
41873
41883
|
function HslInputs({ value, onChange }) {
|
|
41874
|
-
const rgb =
|
|
41884
|
+
const rgb = hexToRgb2(value) ?? { r: 0, g: 0, b: 0 };
|
|
41875
41885
|
const hsl = rgbToHsl(rgb.r, rgb.g, rgb.b);
|
|
41876
41886
|
const update = (next) => {
|
|
41877
41887
|
const h = next.h ?? hsl.h;
|
|
@@ -52465,11 +52475,18 @@ export {
|
|
|
52465
52475
|
ActionsMenu,
|
|
52466
52476
|
ActionsMenuDropdown,
|
|
52467
52477
|
ColorSwatch,
|
|
52478
|
+
DESIGN_PALETTE,
|
|
52479
|
+
getContrastRatio,
|
|
52480
|
+
pickReadableTextColor,
|
|
52481
|
+
extractDominantColor,
|
|
52482
|
+
getBestContrastColor,
|
|
52483
|
+
analyzeImageColor,
|
|
52484
|
+
extractImageEdgeColorAsync,
|
|
52468
52485
|
getPlatformAccentColor,
|
|
52469
52486
|
getCurrentPlatform,
|
|
52470
52487
|
getReadableTextColor,
|
|
52471
52488
|
HEX_PATTERN,
|
|
52472
|
-
hexToRgb,
|
|
52489
|
+
hexToRgb2 as hexToRgb,
|
|
52473
52490
|
rgbToHex,
|
|
52474
52491
|
deriveHoverColor,
|
|
52475
52492
|
deriveActiveColor,
|
|
@@ -53032,18 +53049,11 @@ export {
|
|
|
53032
53049
|
isGenericDomain,
|
|
53033
53050
|
hasGenericEmailDomain,
|
|
53034
53051
|
isGenericWebsiteDomain,
|
|
53035
|
-
DESIGN_PALETTE,
|
|
53036
|
-
getLuminance,
|
|
53037
|
-
getContrastRatio,
|
|
53038
|
-
pickReadableTextColor,
|
|
53039
|
-
extractDominantColor,
|
|
53040
|
-
getBestContrastColor,
|
|
53041
|
-
analyzeImageColor,
|
|
53042
|
-
extractImageEdgeColorAsync,
|
|
53043
53052
|
announcementDismissCookieName,
|
|
53044
53053
|
isDismissedCookieValue,
|
|
53045
53054
|
dismissAnnouncement,
|
|
53046
53055
|
isAnnouncementDismissed,
|
|
53056
|
+
clearAnnouncementDismissals,
|
|
53047
53057
|
clearLegacyAnnouncementCache,
|
|
53048
53058
|
readLeadingDecisionFrame,
|
|
53049
53059
|
ANNOUNCEMENT_CTA_DEFAULTS,
|
|
@@ -53359,4 +53369,4 @@ export {
|
|
|
53359
53369
|
LogsList,
|
|
53360
53370
|
assets
|
|
53361
53371
|
};
|
|
53362
|
-
//# sourceMappingURL=chunk-
|
|
53372
|
+
//# sourceMappingURL=chunk-CVYSW33D.js.map
|