@uva-glass/component-library 3.34.6 → 3.34.8
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/ExpandableInfoPanel.css +1 -1
- package/dist/assets/TextArea.css +1 -1
- package/dist/components/ExpandableInfoPanel/ExpandableInfoPanel.d.ts +4 -2
- package/dist/components/ExpandableInfoPanel/ExpandableInfoPanel.js +36 -30
- package/dist/components/ExpandableInfoPanel/ExpandableInfoPanel.js.map +1 -1
- package/dist/components/ExpandableInfoPanel/ExpandableInfoPanel.stories.d.ts +1 -0
- package/dist/components/ExpandableInfoPanel/ExpandableInfoPanel.stories.js +34 -13
- package/dist/components/ExpandableInfoPanel/ExpandableInfoPanel.stories.js.map +1 -1
- package/dist/components/TextArea/TextArea.js +17 -17
- package/dist/components/hooks/usePositionedFloaters.d.ts +1 -0
- package/dist/components/hooks/usePositionedFloaters.js +18 -17
- package/dist/components/hooks/usePositionedFloaters.js.map +1 -1
- package/package.json +13 -13
|
@@ -1 +1 @@
|
|
|
1
|
-
._expandable-info-
|
|
1
|
+
._expandable-info-panel_wrapper_3n84o_1{display:flex;flex-direction:column;width:100%}._expandable-info-panel_header_3n84o_7{align-items:center;display:flex;flex-direction:row;justify-content:space-between;padding-bottom:.5rem;width:100%}._expandable-info-panel_trigger_3n84o_16{align-items:center;appearance:none;background-color:transparent;border:none;border-radius:.25rem;display:flex;font-size:var(--font-size-default);gap:.5rem;height:2.75rem;margin-bottom:0;outline:none;padding:.5rem;position:relative;width:fit-content;cursor:pointer}._expandable-info-panel_trigger_3n84o_16:focus-visible{outline:.125rem dotted var(--new-color-navy-600);outline-offset:.125rem;text-decoration:underline}._expandable-info-panel_trigger_3n84o_16:hover{background-color:var(--new-color-grey-200);text-decoration:underline}._expandable-info-panel_trigger--active_3n84o_45{background-color:var(--new-color-navy-200);border-radius:.25rem .25rem 0 0}._expandable-info-panel_trigger--active_3n84o_45:after{background-color:var(--new-color-navy-200);content:"";display:block;height:.5rem;left:0;position:absolute;right:0;top:100%;z-index:-1}._expandable-info-panel_trigger--active_3n84o_45:hover,._expandable-info-panel_trigger--active_3n84o_45:hover:after{background-color:var(--new-color-navy-300)}._expandable-info-panel_content-wrapper_3n84o_67{align-items:start;background-color:var(--new-color-navy-200);display:grid;gap:1rem;grid-template-columns:1.5rem 1fr;padding:1.5rem}._expandable-info-panel_content-with-note-container_3n84o_76{display:flex;gap:.5rem;justify-content:space-between}._expandable-info-panel_note_3n84o_82{background-color:var(--new-color-navy-100);padding:1rem;min-width:15.875rem;max-width:15.875rem}
|
package/dist/assets/TextArea.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
._text-
|
|
1
|
+
._text-area__wrapper_2mhm2_1{display:flex;flex-direction:column;gap:.5rem}._text-area__header_2mhm2_7{align-items:flex-end;display:flex;justify-content:space-between}._text-area__label-wrapper_2mhm2_13{display:flex;flex-direction:column;gap:.5rem}._text-area__label_2mhm2_13{font-family:inherit;font-size:inherit;font-weight:var(--semibold)}._text-area__sub-label_2mhm2_25{color:var(--new-color-grey-700);font-size:var(--font-size-text-non-essential)}._text-area__word-count_2mhm2_30{color:var(--new-color-grey-600);font-size:var(--font-size-text-non-essential)}._text-area__word-count--alert_2mhm2_35{color:var(--new-color-red-600);font-weight:700}._text-area_2mhm2_1{border-radius:.5rem;font-family:inherit;font-size:inherit;min-height:5.25rem;overflow:hidden;padding:.5rem;resize:none;white-space:pre-wrap;width:100%;word-wrap:break-word}
|
|
@@ -10,7 +10,9 @@ export interface ExpandableInfoPanelProps {
|
|
|
10
10
|
expandLabel?: string;
|
|
11
11
|
/** Content to be displayed inside the expandable panel. */
|
|
12
12
|
content: ReactNode | string;
|
|
13
|
-
/** Optional
|
|
13
|
+
/** Optional content area on in seperate box on right side of expanded content. */
|
|
14
|
+
note?: ReactNode | string;
|
|
15
|
+
/** Optional state, if true; sets the expandable panel as 'open' by default. */
|
|
14
16
|
defaultOpen?: boolean;
|
|
15
17
|
}
|
|
16
|
-
export declare const ExpandableInfoPanel: ({ triggerLabel, mainHeader, collapseLabel, expandLabel, content, defaultOpen, }: ExpandableInfoPanelProps) => import("react/jsx-runtime").JSX.Element;
|
|
18
|
+
export declare const ExpandableInfoPanel: ({ triggerLabel, mainHeader, collapseLabel, expandLabel, content, note, defaultOpen, }: ExpandableInfoPanelProps) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,47 +1,53 @@
|
|
|
1
|
-
import { jsxs as
|
|
2
|
-
import { useState as
|
|
3
|
-
import { c as
|
|
4
|
-
import { Icon as
|
|
5
|
-
import '../../assets/ExpandableInfoPanel.css';const
|
|
6
|
-
"expandable-info-panel_wrapper": "_expandable-info-
|
|
7
|
-
"expandable-info-panel_header": "_expandable-info-
|
|
8
|
-
"expandable-info-panel_trigger": "_expandable-info-
|
|
9
|
-
"expandable-info-panel_trigger--active": "_expandable-info-panel_trigger--
|
|
10
|
-
"expandable-info-panel_content-wrapper": "_expandable-info-panel_content-
|
|
1
|
+
import { jsxs as o, jsx as a } from "react/jsx-runtime";
|
|
2
|
+
import { useState as x, useId as b } from "react";
|
|
3
|
+
import { c as m } from "../../clsx-OuTLNxxd.js";
|
|
4
|
+
import { Icon as i } from "../Icon/Icon.js";
|
|
5
|
+
import '../../assets/ExpandableInfoPanel.css';const n = {
|
|
6
|
+
"expandable-info-panel_wrapper": "_expandable-info-panel_wrapper_3n84o_1",
|
|
7
|
+
"expandable-info-panel_header": "_expandable-info-panel_header_3n84o_7",
|
|
8
|
+
"expandable-info-panel_trigger": "_expandable-info-panel_trigger_3n84o_16",
|
|
9
|
+
"expandable-info-panel_trigger--active": "_expandable-info-panel_trigger--active_3n84o_45",
|
|
10
|
+
"expandable-info-panel_content-wrapper": "_expandable-info-panel_content-wrapper_3n84o_67",
|
|
11
|
+
"expandable-info-panel_content-with-note-container": "_expandable-info-panel_content-with-note-container_3n84o_76",
|
|
12
|
+
"expandable-info-panel_note": "_expandable-info-panel_note_3n84o_82"
|
|
11
13
|
}, u = ({
|
|
12
14
|
triggerLabel: l,
|
|
13
|
-
mainHeader:
|
|
14
|
-
collapseLabel:
|
|
15
|
-
expandLabel:
|
|
16
|
-
content:
|
|
17
|
-
|
|
15
|
+
mainHeader: d,
|
|
16
|
+
collapseLabel: _ = "",
|
|
17
|
+
expandLabel: c = "",
|
|
18
|
+
content: p,
|
|
19
|
+
note: r = "",
|
|
20
|
+
defaultOpen: s = !1
|
|
18
21
|
}) => {
|
|
19
|
-
const [e,
|
|
20
|
-
return /* @__PURE__ */
|
|
21
|
-
/* @__PURE__ */
|
|
22
|
-
|
|
23
|
-
/* @__PURE__ */
|
|
22
|
+
const [e, f] = x(s), t = b();
|
|
23
|
+
return /* @__PURE__ */ o("div", { className: n["expandable-info-panel_wrapper"], children: [
|
|
24
|
+
/* @__PURE__ */ o("div", { className: n["expandable-info-panel_header"], children: [
|
|
25
|
+
d,
|
|
26
|
+
/* @__PURE__ */ o(
|
|
24
27
|
"button",
|
|
25
28
|
{
|
|
26
|
-
className:
|
|
27
|
-
[
|
|
29
|
+
className: m(n["expandable-info-panel_trigger"], {
|
|
30
|
+
[n["expandable-info-panel_trigger--active"]]: e
|
|
28
31
|
}),
|
|
29
32
|
type: "button",
|
|
30
33
|
"aria-expanded": e,
|
|
31
|
-
"aria-controls":
|
|
32
|
-
"aria-label": `${l} - ${e ?
|
|
33
|
-
onClick: () =>
|
|
34
|
+
"aria-controls": t,
|
|
35
|
+
"aria-label": `${l} - ${e ? _ : c}`,
|
|
36
|
+
onClick: () => f(!e),
|
|
34
37
|
children: [
|
|
35
|
-
/* @__PURE__ */
|
|
38
|
+
/* @__PURE__ */ a(i, { name: e ? "SquareInfoSolid" : "SquareInfo", size: 24 }),
|
|
36
39
|
l,
|
|
37
|
-
/* @__PURE__ */
|
|
40
|
+
/* @__PURE__ */ a(i, { name: e ? "CheveronUp" : "CheveronDown", size: 16 })
|
|
38
41
|
]
|
|
39
42
|
}
|
|
40
43
|
)
|
|
41
44
|
] }),
|
|
42
|
-
e && /* @__PURE__ */
|
|
43
|
-
/* @__PURE__ */
|
|
44
|
-
/* @__PURE__ */
|
|
45
|
+
e && /* @__PURE__ */ o("div", { id: t, className: n["expandable-info-panel_content-wrapper"], children: [
|
|
46
|
+
/* @__PURE__ */ a(i, { name: "SquareInfo", size: 24 }),
|
|
47
|
+
r ? /* @__PURE__ */ o("div", { className: n["expandable-info-panel_content-with-note-container"], children: [
|
|
48
|
+
/* @__PURE__ */ a("div", { children: p }),
|
|
49
|
+
/* @__PURE__ */ a("div", { className: n["expandable-info-panel_note"], children: r })
|
|
50
|
+
] }) : /* @__PURE__ */ a("div", { children: p })
|
|
45
51
|
] })
|
|
46
52
|
] });
|
|
47
53
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExpandableInfoPanel.js","sources":["../../../src/components/ExpandableInfoPanel/ExpandableInfoPanel.tsx"],"sourcesContent":["import { useState, type ReactNode } from 'react';\r\nimport { clsx } from 'clsx';\r\nimport { useId } from 'react';\r\n\r\nimport styles from './ExpandableInfoPanel.module.css';\r\n\r\nimport { Icon } from 'components/Icon';\r\n\r\nexport interface ExpandableInfoPanelProps {\r\n /** Label for the trigger button that toggles the expandable panel. */\r\n triggerLabel: string;\r\n /** Main header displayed inline left of the trigger button. */\r\n mainHeader?: ReactNode | string;\r\n /** Aria-label for the button when the panel is collapsed. */\r\n collapseLabel?: string;\r\n /** Aria-label for the button when the panel is expanded. */\r\n expandLabel?: string;\r\n /** Content to be displayed inside the expandable panel. */\r\n content: ReactNode | string;\r\n /** Optional state. */\r\n defaultOpen?: boolean;\r\n}\r\n\r\nexport const ExpandableInfoPanel = ({\r\n triggerLabel,\r\n mainHeader,\r\n collapseLabel = '',\r\n expandLabel = '',\r\n content,\r\n defaultOpen = false,\r\n}: ExpandableInfoPanelProps) => {\r\n const [active, setActive] = useState(defaultOpen);\r\n const contentId = useId();\r\n\r\n return (\r\n <div className={styles['expandable-info-panel_wrapper']}>\r\n <div className={styles['expandable-info-panel_header']}>\r\n {mainHeader}\r\n <button\r\n className={clsx(styles['expandable-info-panel_trigger'], {\r\n [styles['expandable-info-panel_trigger--active']]: active,\r\n })}\r\n type=\"button\"\r\n aria-expanded={active}\r\n aria-controls={contentId}\r\n aria-label={`${triggerLabel} - ${active ? collapseLabel : expandLabel}`}\r\n onClick={() => setActive(!active)}\r\n >\r\n <Icon name={active ? 'SquareInfoSolid' : 'SquareInfo'} size={24} />\r\n {triggerLabel}\r\n <Icon name={active ? 'CheveronUp' : 'CheveronDown'} size={16} />\r\n </button>\r\n </div>\r\n {active && (\r\n <div id={contentId} className={styles['expandable-info-panel_content-wrapper']}>\r\n <Icon name=\"SquareInfo\" size={24} />\r\n <div>{content}</div>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n};\r\n"],"names":["ExpandableInfoPanel","triggerLabel","mainHeader","collapseLabel","expandLabel","content","defaultOpen","active","setActive","useState","contentId","useId","jsxs","styles","clsx","jsx","Icon"],"mappings":"
|
|
1
|
+
{"version":3,"file":"ExpandableInfoPanel.js","sources":["../../../src/components/ExpandableInfoPanel/ExpandableInfoPanel.tsx"],"sourcesContent":["import { useState, type ReactNode } from 'react';\r\nimport { clsx } from 'clsx';\r\nimport { useId } from 'react';\r\n\r\nimport styles from './ExpandableInfoPanel.module.css';\r\n\r\nimport { Icon } from 'components/Icon';\r\n\r\nexport interface ExpandableInfoPanelProps {\r\n /** Label for the trigger button that toggles the expandable panel. */\r\n triggerLabel: string;\r\n /** Main header displayed inline left of the trigger button. */\r\n mainHeader?: ReactNode | string;\r\n /** Aria-label for the button when the panel is collapsed. */\r\n collapseLabel?: string;\r\n /** Aria-label for the button when the panel is expanded. */\r\n expandLabel?: string;\r\n /** Content to be displayed inside the expandable panel. */\r\n content: ReactNode | string;\r\n /** Optional content area on in seperate box on right side of expanded content. */\r\n note?: ReactNode | string;\r\n /** Optional state, if true; sets the expandable panel as 'open' by default. */\r\n defaultOpen?: boolean;\r\n}\r\n\r\nexport const ExpandableInfoPanel = ({\r\n triggerLabel,\r\n mainHeader,\r\n collapseLabel = '',\r\n expandLabel = '',\r\n content,\r\n note = '',\r\n defaultOpen = false,\r\n}: ExpandableInfoPanelProps) => {\r\n const [active, setActive] = useState(defaultOpen);\r\n const contentId = useId();\r\n\r\n return (\r\n <div className={styles['expandable-info-panel_wrapper']}>\r\n <div className={styles['expandable-info-panel_header']}>\r\n {mainHeader}\r\n <button\r\n className={clsx(styles['expandable-info-panel_trigger'], {\r\n [styles['expandable-info-panel_trigger--active']]: active,\r\n })}\r\n type=\"button\"\r\n aria-expanded={active}\r\n aria-controls={contentId}\r\n aria-label={`${triggerLabel} - ${active ? collapseLabel : expandLabel}`}\r\n onClick={() => setActive(!active)}\r\n >\r\n <Icon name={active ? 'SquareInfoSolid' : 'SquareInfo'} size={24} />\r\n {triggerLabel}\r\n <Icon name={active ? 'CheveronUp' : 'CheveronDown'} size={16} />\r\n </button>\r\n </div>\r\n {active && (\r\n <div id={contentId} className={styles['expandable-info-panel_content-wrapper']}>\r\n <Icon name=\"SquareInfo\" size={24} />\r\n {!note ? (\r\n <div>{content}</div>\r\n ) : (\r\n <div className={styles['expandable-info-panel_content-with-note-container']}>\r\n <div>{content}</div>\r\n <div className={styles['expandable-info-panel_note']}>{note}</div>\r\n </div>\r\n )}\r\n </div>\r\n )}\r\n </div>\r\n );\r\n};\r\n"],"names":["ExpandableInfoPanel","triggerLabel","mainHeader","collapseLabel","expandLabel","content","note","defaultOpen","active","setActive","useState","contentId","useId","jsxs","styles","clsx","jsx","Icon"],"mappings":";;;;;;;;;;;;GAyBaA,IAAsB,CAAC;AAAA,EAClC,cAAAC;AAAA,EACA,YAAAC;AAAA,EACA,eAAAC,IAAgB;AAAA,EAChB,aAAAC,IAAc;AAAA,EACd,SAAAC;AAAA,EACA,MAAAC,IAAO;AAAA,EACP,aAAAC,IAAc;AAChB,MAAgC;AAC9B,QAAM,CAACC,GAAQC,CAAS,IAAIC,EAASH,CAAW,GAC1CI,IAAYC,EAAA;AAElB,SACE,gBAAAC,EAAC,OAAA,EAAI,WAAWC,EAAO,+BAA+B,GACpD,UAAA;AAAA,IAAA,gBAAAD,EAAC,OAAA,EAAI,WAAWC,EAAO,8BAA8B,GAClD,UAAA;AAAA,MAAAZ;AAAA,MACD,gBAAAW;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,WAAWE,EAAKD,EAAO,+BAA+B,GAAG;AAAA,YACvD,CAACA,EAAO,uCAAuC,CAAC,GAAGN;AAAA,UAAA,CACpD;AAAA,UACD,MAAK;AAAA,UACL,iBAAeA;AAAA,UACf,iBAAeG;AAAA,UACf,cAAY,GAAGV,CAAY,MAAMO,IAASL,IAAgBC,CAAW;AAAA,UACrE,SAAS,MAAMK,EAAU,CAACD,CAAM;AAAA,UAEhC,UAAA;AAAA,YAAA,gBAAAQ,EAACC,KAAK,MAAMT,IAAS,oBAAoB,cAAc,MAAM,IAAI;AAAA,YAChEP;AAAA,8BACAgB,GAAA,EAAK,MAAMT,IAAS,eAAe,gBAAgB,MAAM,GAAA,CAAI;AAAA,UAAA;AAAA,QAAA;AAAA,MAAA;AAAA,IAChE,GACF;AAAA,IACCA,uBACE,OAAA,EAAI,IAAIG,GAAW,WAAWG,EAAO,uCAAuC,GAC3E,UAAA;AAAA,MAAA,gBAAAE,EAACC,GAAA,EAAK,MAAK,cAAa,MAAM,IAAI;AAAA,MAChCX,IAGA,gBAAAO,EAAC,OAAA,EAAI,WAAWC,EAAO,mDAAmD,GACxE,UAAA;AAAA,QAAA,gBAAAE,EAAC,SAAK,UAAAX,EAAA,CAAQ;AAAA,0BACb,OAAA,EAAI,WAAWS,EAAO,4BAA4B,GAAI,UAAAR,EAAA,CAAK;AAAA,MAAA,EAAA,CAC9D,IALA,gBAAAU,EAAC,OAAA,EAAK,UAAAX,EAAA,CAAQ;AAAA,IAKd,EAAA,CAEJ;AAAA,EAAA,GAEJ;AAEJ;"}
|
|
@@ -3,3 +3,4 @@ import { ExpandableInfoPanelProps } from './ExpandableInfoPanel';
|
|
|
3
3
|
declare const _default: Meta<ExpandableInfoPanelProps>;
|
|
4
4
|
export default _default;
|
|
5
5
|
export declare const ExpandableInfoPanelExample: import('storybook/internal/csf').AnnotatedStoryFn<import('@storybook/react').ReactRenderer, ExpandableInfoPanelProps>;
|
|
6
|
+
export declare const DefaultOpenWithNote: import('storybook/internal/csf').AnnotatedStoryFn<import('@storybook/react').ReactRenderer, ExpandableInfoPanelProps>;
|
|
@@ -1,22 +1,23 @@
|
|
|
1
|
-
import { jsxs as
|
|
2
|
-
import { ExpandableInfoPanel as
|
|
3
|
-
|
|
1
|
+
import { jsxs as n, jsx as e, Fragment as t } from "react/jsx-runtime";
|
|
2
|
+
import { ExpandableInfoPanel as a } from "./ExpandableInfoPanel.js";
|
|
3
|
+
import { Repeater as o } from "../Repeater/Repeater.js";
|
|
4
|
+
const s = "<ExpandableInfoPanel triggerLabel={string} mainHeader={string or reactnode} collapseLabel={string} expandLabel={string} content={string or reactnode} />", m = {
|
|
4
5
|
title: "Molecules/ExpandableInfoPanel",
|
|
5
|
-
component:
|
|
6
|
+
component: a,
|
|
6
7
|
parameters: {
|
|
7
|
-
inspectComponent:
|
|
8
|
-
codeString:
|
|
8
|
+
inspectComponent: a,
|
|
9
|
+
codeString: s
|
|
9
10
|
}
|
|
10
|
-
},
|
|
11
|
-
/* @__PURE__ */ e(
|
|
11
|
+
}, i = (r) => /* @__PURE__ */ n(t, { children: [
|
|
12
|
+
/* @__PURE__ */ e(a, { ...r }),
|
|
12
13
|
/* @__PURE__ */ e("div", { style: { marginTop: "1rem" }, children: "De universiteit biedt een breed scala aan vakken aan, variërend van exacte wetenschappen tot geesteswetenschappen. Studenten kunnen kiezen uit uitdagende keuzevakken, minors en specialisaties die hun studie verrijken. Deze vaklaanbiedingen stimuleren interdisciplinair leren, persoonlijke ontwikkeling en academische verdieping, afgestemd op actuele maatschappelijke vraagstukken en de behoeften van de arbeidsmarkt." })
|
|
13
|
-
] }),
|
|
14
|
-
|
|
14
|
+
] }), l = i.bind({});
|
|
15
|
+
l.args = {
|
|
15
16
|
triggerLabel: "Wat moet ik doen?",
|
|
16
17
|
mainHeader: /* @__PURE__ */ e("h1", { children: "Basisgegevens" }),
|
|
17
18
|
collapseLabel: "Sluit informatiepaneel",
|
|
18
19
|
expandLabel: "Open informatiepaneel",
|
|
19
|
-
content: /* @__PURE__ */
|
|
20
|
+
content: /* @__PURE__ */ n(t, { children: [
|
|
20
21
|
/* @__PURE__ */ e("h3", { style: { marginTop: "0" }, children: "Wat moet ik doen?" }),
|
|
21
22
|
/* @__PURE__ */ e("span", { children: "Controleer de onderstaande basisgegevens. Klik daarna op ‘Start’ om te beginnen met het invoeren van de roosterwensen. Je kunt tussentijds opslaan en op een later moment verdergaan." }),
|
|
22
23
|
/* @__PURE__ */ e("br", {}),
|
|
@@ -24,8 +25,28 @@ s.args = {
|
|
|
24
25
|
/* @__PURE__ */ e("span", { children: "Kloppen de gegevens niet? Neem contact op met de opleidingscoördinator." })
|
|
25
26
|
] })
|
|
26
27
|
};
|
|
28
|
+
const d = i.bind({});
|
|
29
|
+
d.args = {
|
|
30
|
+
triggerLabel: "Wat moet ik doen?",
|
|
31
|
+
mainHeader: /* @__PURE__ */ e("h1", { children: "Basisgegevens" }),
|
|
32
|
+
collapseLabel: "Sluit informatiepaneel",
|
|
33
|
+
expandLabel: "Open informatiepaneel",
|
|
34
|
+
content: /* @__PURE__ */ n(t, { children: [
|
|
35
|
+
/* @__PURE__ */ e("h3", { style: { marginTop: "0" }, children: "Wat moet ik doen?" }),
|
|
36
|
+
/* @__PURE__ */ e("span", { children: "Controleer de onderstaande basisgegevens. Klik daarna op ‘Start’ om te beginnen met het invoeren van de roosterwensen. Je kunt tussentijds opslaan en op een later moment verdergaan." }),
|
|
37
|
+
/* @__PURE__ */ e("br", {}),
|
|
38
|
+
/* @__PURE__ */ e("br", {}),
|
|
39
|
+
/* @__PURE__ */ e("span", { children: "Kloppen de gegevens niet? Neem contact op met de opleidingscoördinator." })
|
|
40
|
+
] }),
|
|
41
|
+
note: /* @__PURE__ */ n(o, { gap: "050", children: [
|
|
42
|
+
/* @__PURE__ */ e("span", { style: { fontWeight: "700" }, children: "Let op" }),
|
|
43
|
+
/* @__PURE__ */ e("span", { children: "hier kunt u een extra opmerking achterlaten om de inhoud van uw gewone paneel te versterken." })
|
|
44
|
+
] }),
|
|
45
|
+
defaultOpen: !0
|
|
46
|
+
};
|
|
27
47
|
export {
|
|
28
|
-
|
|
29
|
-
|
|
48
|
+
d as DefaultOpenWithNote,
|
|
49
|
+
l as ExpandableInfoPanelExample,
|
|
50
|
+
m as default
|
|
30
51
|
};
|
|
31
52
|
//# sourceMappingURL=ExpandableInfoPanel.stories.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExpandableInfoPanel.stories.js","sources":["../../../src/components/ExpandableInfoPanel/ExpandableInfoPanel.stories.tsx"],"sourcesContent":["import type { Meta, StoryFn } from '@storybook/react';\r\nimport type { ExpandableInfoPanelProps } from './ExpandableInfoPanel';\r\n\r\nimport { ExpandableInfoPanel } from './ExpandableInfoPanel';\r\n\r\nconst codeString =\r\n '<ExpandableInfoPanel triggerLabel={string} mainHeader={string or reactnode} collapseLabel={string} expandLabel={string} content={string or reactnode} />';\r\n\r\n// eslint-disable-next-line import/no-default-export\r\nexport default {\r\n title: 'Molecules/ExpandableInfoPanel',\r\n component: ExpandableInfoPanel,\r\n parameters: {\r\n inspectComponent: ExpandableInfoPanel,\r\n codeString: codeString,\r\n },\r\n} as Meta<ExpandableInfoPanelProps>;\r\n\r\nconst Template: StoryFn<ExpandableInfoPanelProps> = (args) => (\r\n <>\r\n <ExpandableInfoPanel {...args} />\r\n <div style={{ marginTop: '1rem' }}>\r\n De universiteit biedt een breed scala aan vakken aan, variërend van exacte wetenschappen tot geesteswetenschappen.\r\n Studenten kunnen kiezen uit uitdagende keuzevakken, minors en specialisaties die hun studie verrijken. Deze\r\n vaklaanbiedingen stimuleren interdisciplinair leren, persoonlijke ontwikkeling en academische verdieping,\r\n afgestemd op actuele maatschappelijke vraagstukken en de behoeften van de arbeidsmarkt.\r\n </div>\r\n </>\r\n);\r\n\r\nexport const ExpandableInfoPanelExample = Template.bind({});\r\nExpandableInfoPanelExample.args = {\r\n triggerLabel: 'Wat moet ik doen?',\r\n mainHeader: <h1>Basisgegevens</h1>,\r\n collapseLabel: 'Sluit informatiepaneel',\r\n expandLabel: 'Open informatiepaneel',\r\n content: (\r\n <>\r\n <h3 style={{ marginTop: '0' }}>Wat moet ik doen?</h3>\r\n <span>\r\n Controleer de onderstaande basisgegevens. Klik daarna op ‘Start’ om te beginnen met het invoeren van de\r\n roosterwensen. Je kunt tussentijds opslaan en op een later moment verdergaan.\r\n </span>\r\n <br />\r\n <br />\r\n <span>Kloppen de gegevens niet? Neem contact op met de opleidingscoördinator.</span>\r\n </>\r\n ),\r\n};\r\n"],"names":["codeString","ExpandableInfoPanel_stories","ExpandableInfoPanel","Template","args","jsxs","Fragment","jsx","ExpandableInfoPanelExample"],"mappings":"
|
|
1
|
+
{"version":3,"file":"ExpandableInfoPanel.stories.js","sources":["../../../src/components/ExpandableInfoPanel/ExpandableInfoPanel.stories.tsx"],"sourcesContent":["import type { Meta, StoryFn } from '@storybook/react';\r\nimport type { ExpandableInfoPanelProps } from './ExpandableInfoPanel';\r\n\r\nimport { ExpandableInfoPanel } from './ExpandableInfoPanel';\r\n\r\nimport { Repeater } from 'components/Repeater';\r\n\r\nconst codeString =\r\n '<ExpandableInfoPanel triggerLabel={string} mainHeader={string or reactnode} collapseLabel={string} expandLabel={string} content={string or reactnode} />';\r\n\r\n// eslint-disable-next-line import/no-default-export\r\nexport default {\r\n title: 'Molecules/ExpandableInfoPanel',\r\n component: ExpandableInfoPanel,\r\n parameters: {\r\n inspectComponent: ExpandableInfoPanel,\r\n codeString: codeString,\r\n },\r\n} as Meta<ExpandableInfoPanelProps>;\r\n\r\nconst Template: StoryFn<ExpandableInfoPanelProps> = (args) => (\r\n <>\r\n <ExpandableInfoPanel {...args} />\r\n <div style={{ marginTop: '1rem' }}>\r\n De universiteit biedt een breed scala aan vakken aan, variërend van exacte wetenschappen tot geesteswetenschappen.\r\n Studenten kunnen kiezen uit uitdagende keuzevakken, minors en specialisaties die hun studie verrijken. Deze\r\n vaklaanbiedingen stimuleren interdisciplinair leren, persoonlijke ontwikkeling en academische verdieping,\r\n afgestemd op actuele maatschappelijke vraagstukken en de behoeften van de arbeidsmarkt.\r\n </div>\r\n </>\r\n);\r\n\r\nexport const ExpandableInfoPanelExample = Template.bind({});\r\nExpandableInfoPanelExample.args = {\r\n triggerLabel: 'Wat moet ik doen?',\r\n mainHeader: <h1>Basisgegevens</h1>,\r\n collapseLabel: 'Sluit informatiepaneel',\r\n expandLabel: 'Open informatiepaneel',\r\n content: (\r\n <>\r\n <h3 style={{ marginTop: '0' }}>Wat moet ik doen?</h3>\r\n <span>\r\n Controleer de onderstaande basisgegevens. Klik daarna op ‘Start’ om te beginnen met het invoeren van de\r\n roosterwensen. Je kunt tussentijds opslaan en op een later moment verdergaan.\r\n </span>\r\n <br />\r\n <br />\r\n <span>Kloppen de gegevens niet? Neem contact op met de opleidingscoördinator.</span>\r\n </>\r\n ),\r\n};\r\n\r\nexport const DefaultOpenWithNote = Template.bind({});\r\nDefaultOpenWithNote.args = {\r\n triggerLabel: 'Wat moet ik doen?',\r\n mainHeader: <h1>Basisgegevens</h1>,\r\n collapseLabel: 'Sluit informatiepaneel',\r\n expandLabel: 'Open informatiepaneel',\r\n content: (\r\n <>\r\n <h3 style={{ marginTop: '0' }}>Wat moet ik doen?</h3>\r\n <span>\r\n Controleer de onderstaande basisgegevens. Klik daarna op ‘Start’ om te beginnen met het invoeren van de\r\n roosterwensen. Je kunt tussentijds opslaan en op een later moment verdergaan.\r\n </span>\r\n <br />\r\n <br />\r\n <span>Kloppen de gegevens niet? Neem contact op met de opleidingscoördinator.</span>\r\n </>\r\n ),\r\n note: (\r\n <Repeater gap=\"050\">\r\n <span style={{ fontWeight: '700' }}>Let op</span>\r\n <span>hier kunt u een extra opmerking achterlaten om de inhoud van uw gewone paneel te versterken.</span>\r\n </Repeater>\r\n ),\r\n defaultOpen: true,\r\n};\r\n"],"names":["codeString","ExpandableInfoPanel_stories","ExpandableInfoPanel","Template","args","jsxs","Fragment","jsx","ExpandableInfoPanelExample","DefaultOpenWithNote","Repeater"],"mappings":";;;AAOA,MAAMA,IACJ,4JAGFC,IAAe;AAAA,EACb,OAAO;AAAA,EACP,WAAWC;AAAA,EACX,YAAY;AAAA,IACV,kBAAkBA;AAAA,IAClB,YAAAF;AAAA,EAAA;AAEJ,GAEMG,IAA8C,CAACC,MACnD,gBAAAC,EAAAC,GAAA,EACE,UAAA;AAAA,EAAA,gBAAAC,EAACL,GAAA,EAAqB,GAAGE,GAAM;AAAA,oBAC9B,OAAA,EAAI,OAAO,EAAE,WAAW,OAAA,GAAU,UAAA,maAAA,CAKnC;AAAA,GACF,GAGWI,IAA6BL,EAAS,KAAK,CAAA,CAAE;AAC1DK,EAA2B,OAAO;AAAA,EAChC,cAAc;AAAA,EACd,YAAY,gBAAAD,EAAC,MAAA,EAAG,UAAA,gBAAA,CAAa;AAAA,EAC7B,eAAe;AAAA,EACf,aAAa;AAAA,EACb,SACE,gBAAAF,EAAAC,GAAA,EACE,UAAA;AAAA,IAAA,gBAAAC,EAAC,QAAG,OAAO,EAAE,WAAW,IAAA,GAAO,UAAA,qBAAiB;AAAA,IAChD,gBAAAA,EAAC,UAAK,UAAA,wLAAA,CAGN;AAAA,sBACC,MAAA,EAAG;AAAA,sBACH,MAAA,EAAG;AAAA,IACJ,gBAAAA,EAAC,UAAK,UAAA,0EAAA,CAAuE;AAAA,EAAA,EAAA,CAC/E;AAEJ;AAEO,MAAME,IAAsBN,EAAS,KAAK,CAAA,CAAE;AACnDM,EAAoB,OAAO;AAAA,EACzB,cAAc;AAAA,EACd,YAAY,gBAAAF,EAAC,MAAA,EAAG,UAAA,gBAAA,CAAa;AAAA,EAC7B,eAAe;AAAA,EACf,aAAa;AAAA,EACb,SACE,gBAAAF,EAAAC,GAAA,EACE,UAAA;AAAA,IAAA,gBAAAC,EAAC,QAAG,OAAO,EAAE,WAAW,IAAA,GAAO,UAAA,qBAAiB;AAAA,IAChD,gBAAAA,EAAC,UAAK,UAAA,wLAAA,CAGN;AAAA,sBACC,MAAA,EAAG;AAAA,sBACH,MAAA,EAAG;AAAA,IACJ,gBAAAA,EAAC,UAAK,UAAA,0EAAA,CAAuE;AAAA,EAAA,GAC/E;AAAA,EAEF,MACE,gBAAAF,EAACK,GAAA,EAAS,KAAI,OACZ,UAAA;AAAA,IAAA,gBAAAH,EAAC,UAAK,OAAO,EAAE,YAAY,MAAA,GAAS,UAAA,UAAM;AAAA,IAC1C,gBAAAA,EAAC,UAAK,UAAA,+FAAA,CAA4F;AAAA,EAAA,GACpG;AAAA,EAEF,aAAa;AACf;"}
|
|
@@ -1,28 +1,28 @@
|
|
|
1
1
|
import { jsxs as r, jsx as _ } from "react/jsx-runtime";
|
|
2
|
-
import { useRef as
|
|
3
|
-
import { c as
|
|
2
|
+
import { useRef as h, useState as u } from "react";
|
|
3
|
+
import { c as p } from "../../clsx-OuTLNxxd.js";
|
|
4
4
|
import '../../assets/TextArea.css';const e = {
|
|
5
|
-
"text-area__wrapper": "_text-
|
|
6
|
-
"text-area__header": "_text-
|
|
7
|
-
"text-area__label-wrapper": "_text-area__label-
|
|
8
|
-
"text-area__label": "_text-
|
|
9
|
-
"text-area__sub-label": "_text-area__sub-
|
|
10
|
-
"text-area__word-count": "_text-area__word-
|
|
11
|
-
"text-area__word-count--alert": "_text-area__word-count--
|
|
12
|
-
"text-area": "_text-
|
|
5
|
+
"text-area__wrapper": "_text-area__wrapper_2mhm2_1",
|
|
6
|
+
"text-area__header": "_text-area__header_2mhm2_7",
|
|
7
|
+
"text-area__label-wrapper": "_text-area__label-wrapper_2mhm2_13",
|
|
8
|
+
"text-area__label": "_text-area__label_2mhm2_13",
|
|
9
|
+
"text-area__sub-label": "_text-area__sub-label_2mhm2_25",
|
|
10
|
+
"text-area__word-count": "_text-area__word-count_2mhm2_30",
|
|
11
|
+
"text-area__word-count--alert": "_text-area__word-count--alert_2mhm2_35",
|
|
12
|
+
"text-area": "_text-area_2mhm2_1"
|
|
13
13
|
};
|
|
14
|
-
function b({ onChange:
|
|
15
|
-
const t =
|
|
16
|
-
t.current && (t.current.style.height = "auto", t.current.style.height = `${t.current.scrollHeight}px`,
|
|
14
|
+
function b({ onChange: o, label: l, subLabel: n, maxCharacters: a = 0, defaultValue: s = "" }) {
|
|
15
|
+
const t = h(null), [c, x] = u(s.length), m = () => {
|
|
16
|
+
t.current && (t.current.style.height = "auto", t.current.style.height = `${t.current.scrollHeight}px`, x(t.current.value.length), o(t.current.value.trim()));
|
|
17
17
|
};
|
|
18
18
|
return /* @__PURE__ */ r("div", { className: e["text-area__wrapper"], children: [
|
|
19
19
|
(l || a > 0) && /* @__PURE__ */ r("div", { className: e["text-area__header"], children: [
|
|
20
20
|
/* @__PURE__ */ r("span", { className: e["text-area__label-wrapper"], children: [
|
|
21
21
|
l && /* @__PURE__ */ _("span", { className: e["text-area__label"], children: l }),
|
|
22
|
-
|
|
22
|
+
n && /* @__PURE__ */ _("span", { className: e["text-area__sub-label"], children: n })
|
|
23
23
|
] }),
|
|
24
24
|
a > 0 && /* @__PURE__ */ r("div", { className: e["text-area__word-count"], children: [
|
|
25
|
-
/* @__PURE__ */ _("span", { className:
|
|
25
|
+
/* @__PURE__ */ _("span", { className: p({ [e["text-area__word-count--alert"]]: c === a }), children: c }),
|
|
26
26
|
" / ",
|
|
27
27
|
a
|
|
28
28
|
] })
|
|
@@ -33,8 +33,8 @@ function b({ onChange: u, label: l, subLabel: s, maxCharacters: a = 0, defaultVa
|
|
|
33
33
|
ref: t,
|
|
34
34
|
className: e["text-area"],
|
|
35
35
|
maxLength: a > 0 ? a : void 0,
|
|
36
|
-
onInput:
|
|
37
|
-
defaultValue:
|
|
36
|
+
onInput: m,
|
|
37
|
+
defaultValue: s
|
|
38
38
|
}
|
|
39
39
|
)
|
|
40
40
|
] });
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { useState as
|
|
1
|
+
import { useState as H, useEffect as P } from "react";
|
|
2
2
|
import { useDebounce as $ } from "./useDebounce.js";
|
|
3
3
|
const a = 10, F = 90, r = 300, y = 0, B = 768, k = 2;
|
|
4
4
|
function M(c, n, i) {
|
|
5
|
-
const [m,
|
|
5
|
+
const [m, p] = H(!1), w = {
|
|
6
6
|
inset: "0 auto auto 0",
|
|
7
7
|
opacity: 0,
|
|
8
8
|
maxHeight: "100%",
|
|
@@ -11,30 +11,30 @@ function M(c, n, i) {
|
|
|
11
11
|
overflowX: "hidden",
|
|
12
12
|
overflowY: "auto",
|
|
13
13
|
margin: "0rem"
|
|
14
|
-
}, [l, v] =
|
|
14
|
+
}, [l, v] = H(w), h = (t) => {
|
|
15
15
|
const e = parseFloat(getComputedStyle(document.documentElement).fontSize);
|
|
16
16
|
return t.indexOf("rem") !== -1 ? parseFloat(t) * e : parseFloat(t);
|
|
17
|
-
},
|
|
17
|
+
}, b = (t, e) => {
|
|
18
18
|
if (!t) return 0;
|
|
19
19
|
const o = e === "bottom" ? window.innerHeight - t.bottom - i.offset - a : t.top - i.offset - a;
|
|
20
20
|
return !i.maxFixedHeight || h(i.maxFixedHeight) > o ? o : h(i.maxFixedHeight);
|
|
21
|
-
},
|
|
21
|
+
}, E = (t, e) => {
|
|
22
22
|
if (!t) return 0;
|
|
23
23
|
const o = e === "left" ? window.innerWidth - t.left - a : t.right - a;
|
|
24
24
|
return o <= r ? r : o;
|
|
25
|
-
},
|
|
25
|
+
}, W = (t, e, o) => o ? `${t.left - Math.abs(e.width - t.width) / k}px` : `${t.left}px`, f = () => {
|
|
26
26
|
const t = c?.getBoundingClientRect(), e = n?.getBoundingClientRect();
|
|
27
27
|
let o = "bottom", d = "left";
|
|
28
|
-
const
|
|
28
|
+
const L = window.matchMedia(
|
|
29
29
|
`(max-width: ${i.mobileBreakpoint ? h(i.mobileBreakpoint) : B}px)`
|
|
30
30
|
).matches;
|
|
31
|
-
return !e || !t ? w : (window.innerHeight - e.bottom - a < F && (o = "top"), (window.innerWidth - e.left - a < r || i.horizontalPosition === "right") && !
|
|
31
|
+
return !e || !t ? w : (window.innerHeight - e.bottom - a < F && (o = "top"), (window.innerWidth - e.left - a < r || i.horizontalPosition === "right") && !L && (d = "right"), {
|
|
32
32
|
inset: `${o === "bottom" ? e[o] + "px" : "auto"}
|
|
33
33
|
${d === "right" ? window.innerWidth - e[d] + "px" : "auto"}
|
|
34
34
|
${o === "top" ? window.innerHeight - e[o] + "px" : "auto"}
|
|
35
|
-
${d === "left" ?
|
|
36
|
-
maxHeight: `${
|
|
37
|
-
maxWidth: `${
|
|
35
|
+
${d === "left" ? W(e, t, L) : "auto"}`,
|
|
36
|
+
maxHeight: `${b(e, o)}px`,
|
|
37
|
+
maxWidth: `${E(e, d)}px`,
|
|
38
38
|
minWidth: i.fullWidth ? e.width : r,
|
|
39
39
|
overflowX: "hidden",
|
|
40
40
|
overflowY: "auto",
|
|
@@ -45,22 +45,23 @@ function M(c, n, i) {
|
|
|
45
45
|
v({
|
|
46
46
|
...l,
|
|
47
47
|
...f()
|
|
48
|
-
}),
|
|
49
|
-
},
|
|
48
|
+
}), p(!0);
|
|
49
|
+
}, x = () => {
|
|
50
50
|
m && v({
|
|
51
51
|
...l,
|
|
52
52
|
...f()
|
|
53
53
|
});
|
|
54
54
|
}, s = (t) => {
|
|
55
55
|
!n || n.contains(t.target) || !c || c.contains(t.target);
|
|
56
|
-
},
|
|
57
|
-
return P(() => (n !== null && (i.mouseEvent === "click" ? n.addEventListener("click", u) : (n.addEventListener("mouseenter", u), n.addEventListener("mouseleave", s)), document.addEventListener("mousedown", s), document.addEventListener("touchstart", s), window.addEventListener("resize",
|
|
58
|
-
n !== null && (i.mouseEvent === "click" ? n.removeEventListener("click", u) : (n.removeEventListener("mouseenter", u), n.removeEventListener("mouseleave", s)), document.removeEventListener("mousedown", s), document.removeEventListener("touchstart", s), window.removeEventListener("resize",
|
|
56
|
+
}, g = $(x, y);
|
|
57
|
+
return P(() => (n !== null && (i.mouseEvent === "click" ? n.addEventListener("click", u) : (n.addEventListener("mouseenter", u), n.addEventListener("mouseleave", s)), document.addEventListener("mousedown", s), document.addEventListener("touchstart", s), window.addEventListener("resize", g)), () => {
|
|
58
|
+
n !== null && (i.mouseEvent === "click" ? n.removeEventListener("click", u) : (n.removeEventListener("mouseenter", u), n.removeEventListener("mouseleave", s)), document.removeEventListener("mousedown", s), document.removeEventListener("touchstart", s), window.removeEventListener("resize", g));
|
|
59
59
|
})), {
|
|
60
60
|
style: {
|
|
61
61
|
style: l
|
|
62
62
|
},
|
|
63
|
-
status: m
|
|
63
|
+
status: m,
|
|
64
|
+
updatePosition: x
|
|
64
65
|
};
|
|
65
66
|
}
|
|
66
67
|
export {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"usePositionedFloaters.js","sources":["../../../src/components/hooks/usePositionedFloaters.ts"],"sourcesContent":["import { useEffect, useState } from 'react';\n\nimport { useDebounce } from './useDebounce';\n\ninterface positionProps {\n style: {\n style: {\n inset: string;\n };\n };\n status: boolean;\n}\n\ninterface optionProps {\n mouseEvent: 'click' | 'hover';\n position: 'bottomLeft' | 'bottomRight' | 'topLeft' | 'topRight';\n offset: number;\n maxFixedHeight?: `${number}${'px' | 'rem'}`;\n horizontalPosition?: 'left' | 'right';\n mobileBreakpoint?: `${number}${'px' | 'rem'}`;\n fullWidth: boolean;\n}\n\nconst BODY_PADDING = 10;\nconst MIN_HEIGHT = 90;\nconst MIN_WIDTH = 300;\nconst DEBOUNCE_DELAY = 0;\nconst MOBILE_BREAKPOINT = 768;\nconst HALF = 2;\n\nexport function usePositionedFloaters<T extends HTMLElement = HTMLElement>(\n positionedElement: T | null,\n referenceElement: T | null,\n options: optionProps\n): positionProps {\n const [status, setStatus] = useState(false);\n const defaultStyle = {\n inset: '0 auto auto 0',\n opacity: 0,\n maxHeight: '100%',\n maxWidth: '100%',\n minWidth: MIN_WIDTH,\n overflowX: 'hidden',\n overflowY: 'auto',\n margin: '0rem',\n };\n\n const [style, setStyle] = useState(defaultStyle);\n\n const sizeToPx = (size: `${number}${'px' | 'rem'}`): number => {\n const rootFontSize = parseFloat(getComputedStyle(document.documentElement).fontSize);\n return size.indexOf('rem') !== -1 ? parseFloat(size) * rootFontSize : parseFloat(size);\n };\n\n const setHeight = (refRect: DOMRect, pos: string): number => {\n if (!refRect) return 0;\n\n const _maxHeight =\n pos === 'bottom'\n ? window.innerHeight - refRect.bottom - options.offset - BODY_PADDING\n : refRect.top - options.offset - BODY_PADDING;\n\n return !options.maxFixedHeight || sizeToPx(options.maxFixedHeight) > _maxHeight\n ? _maxHeight\n : sizeToPx(options.maxFixedHeight);\n };\n\n const setWidth = (refRect: DOMRect, pos: string): number => {\n if (!refRect) return 0;\n\n const _availableWidth =\n pos === 'left' ? window.innerWidth - refRect.left - BODY_PADDING : refRect.right - BODY_PADDING;\n\n return _availableWidth <= MIN_WIDTH ? MIN_WIDTH : _availableWidth;\n };\n\n const setLeft = (refRect: DOMRect, posRect: DOMRect, isMobile: boolean) => {\n if (isMobile) {\n return `${refRect.left - Math.abs(posRect.width - refRect.width) / HALF}px`;\n } else {\n return `${refRect.left}px`;\n }\n };\n\n const calcPosition = (): typeof defaultStyle => {\n const positionedRect = (positionedElement as HTMLElement | null)?.getBoundingClientRect();\n const referenceRect = (referenceElement as HTMLElement | null)?.getBoundingClientRect();\n let yPos = 'bottom';\n let xPos = 'left';\n\n const isMobile = window.matchMedia(\n `(max-width: ${options.mobileBreakpoint ? sizeToPx(options.mobileBreakpoint) : MOBILE_BREAKPOINT}px)`\n ).matches;\n\n if (!referenceRect || !positionedRect) {\n return defaultStyle;\n }\n\n if (window.innerHeight - referenceRect.bottom - BODY_PADDING < MIN_HEIGHT) {\n yPos = 'top';\n }\n\n if (\n (window.innerWidth - referenceRect.left - BODY_PADDING < MIN_WIDTH || options.horizontalPosition === 'right') &&\n !isMobile\n ) {\n xPos = 'right';\n }\n\n return {\n inset: `${yPos === 'bottom' ? referenceRect[yPos] + 'px' : 'auto'}\n ${xPos === 'right' ? window.innerWidth - referenceRect[xPos] + 'px' : 'auto'}\n ${yPos === 'top' ? window.innerHeight - referenceRect[yPos] + 'px' : 'auto'}\n ${xPos === 'left' ? setLeft(referenceRect, positionedRect, isMobile) : 'auto'}`,\n maxHeight: `${setHeight(referenceRect, yPos)}px`,\n maxWidth: `${setWidth(referenceRect, xPos)}px`,\n minWidth: options.fullWidth ? referenceRect.width : MIN_WIDTH,\n overflowX: 'hidden',\n overflowY: 'auto',\n opacity: 1,\n margin: `${options.offset}px 0`,\n };\n };\n\n const handleMouseEvent = (): void => {\n setStyle({\n ...style,\n ...calcPosition(),\n });\n setStatus(true);\n };\n\n const updatePosition = (): void => {\n if (status) {\n setStyle({\n ...style,\n ...calcPosition(),\n });\n }\n };\n\n const handleClickOutside = (evt: Event): void => {\n if (\n !referenceElement ||\n (referenceElement as unknown as HTMLElement).contains(evt.target as Node) ||\n !positionedElement ||\n (positionedElement as unknown as HTMLElement).contains(evt.target as Node)\n ) {\n return;\n }\n };\n\n const debouncedUpdatePosition = useDebounce(updatePosition, DEBOUNCE_DELAY);\n\n useEffect(() => {\n if (referenceElement !== null) {\n if (options.mouseEvent === 'click') {\n // eslint-disable-next-line no-extra-semi\n (referenceElement as unknown as HTMLElement).addEventListener('click', handleMouseEvent);\n } else {\n // eslint-disable-next-line no-extra-semi\n (referenceElement as unknown as HTMLElement).addEventListener('mouseenter', handleMouseEvent);\n // eslint-disable-next-line no-extra-semi\n (referenceElement as unknown as HTMLElement).addEventListener('mouseleave', handleClickOutside);\n }\n document.addEventListener('mousedown', handleClickOutside);\n document.addEventListener('touchstart', handleClickOutside);\n window.addEventListener('resize', debouncedUpdatePosition);\n }\n\n return () => {\n if (referenceElement !== null) {\n if (options.mouseEvent === 'click') {\n // eslint-disable-next-line no-extra-semi\n (referenceElement as unknown as HTMLElement).removeEventListener('click', handleMouseEvent);\n } else {\n // eslint-disable-next-line no-extra-semi\n (referenceElement as unknown as HTMLElement).removeEventListener('mouseenter', handleMouseEvent);\n // eslint-disable-next-line no-extra-semi\n (referenceElement as unknown as HTMLElement).removeEventListener('mouseleave', handleClickOutside);\n }\n document.removeEventListener('mousedown', handleClickOutside);\n document.removeEventListener('touchstart', handleClickOutside);\n window.removeEventListener('resize', debouncedUpdatePosition);\n }\n };\n });\n\n return {\n style: {\n style,\n },\n status,\n };\n}\n"],"names":["BODY_PADDING","MIN_HEIGHT","MIN_WIDTH","DEBOUNCE_DELAY","MOBILE_BREAKPOINT","HALF","usePositionedFloaters","positionedElement","referenceElement","options","status","setStatus","useState","defaultStyle","style","setStyle","sizeToPx","size","rootFontSize","setHeight","refRect","pos","_maxHeight","setWidth","_availableWidth","setLeft","posRect","isMobile","calcPosition","positionedRect","referenceRect","yPos","xPos","handleMouseEvent","updatePosition","handleClickOutside","evt","debouncedUpdatePosition","useDebounce","useEffect"],"mappings":";;
|
|
1
|
+
{"version":3,"file":"usePositionedFloaters.js","sources":["../../../src/components/hooks/usePositionedFloaters.ts"],"sourcesContent":["import { useEffect, useState } from 'react';\n\nimport { useDebounce } from './useDebounce';\n\ninterface positionProps {\n style: {\n style: {\n inset: string;\n };\n };\n status: boolean;\n updatePosition: () => void;\n}\n\ninterface optionProps {\n mouseEvent: 'click' | 'hover';\n position: 'bottomLeft' | 'bottomRight' | 'topLeft' | 'topRight';\n offset: number;\n maxFixedHeight?: `${number}${'px' | 'rem'}`;\n horizontalPosition?: 'left' | 'right';\n mobileBreakpoint?: `${number}${'px' | 'rem'}`;\n fullWidth: boolean;\n}\n\nconst BODY_PADDING = 10;\nconst MIN_HEIGHT = 90;\nconst MIN_WIDTH = 300;\nconst DEBOUNCE_DELAY = 0;\nconst MOBILE_BREAKPOINT = 768;\nconst HALF = 2;\n\nexport function usePositionedFloaters<T extends HTMLElement = HTMLElement>(\n positionedElement: T | null,\n referenceElement: T | null,\n options: optionProps\n): positionProps {\n const [status, setStatus] = useState(false);\n const defaultStyle = {\n inset: '0 auto auto 0',\n opacity: 0,\n maxHeight: '100%',\n maxWidth: '100%',\n minWidth: MIN_WIDTH,\n overflowX: 'hidden',\n overflowY: 'auto',\n margin: '0rem',\n };\n\n const [style, setStyle] = useState(defaultStyle);\n\n const sizeToPx = (size: `${number}${'px' | 'rem'}`): number => {\n const rootFontSize = parseFloat(getComputedStyle(document.documentElement).fontSize);\n return size.indexOf('rem') !== -1 ? parseFloat(size) * rootFontSize : parseFloat(size);\n };\n\n const setHeight = (refRect: DOMRect, pos: string): number => {\n if (!refRect) return 0;\n\n const _maxHeight =\n pos === 'bottom'\n ? window.innerHeight - refRect.bottom - options.offset - BODY_PADDING\n : refRect.top - options.offset - BODY_PADDING;\n\n return !options.maxFixedHeight || sizeToPx(options.maxFixedHeight) > _maxHeight\n ? _maxHeight\n : sizeToPx(options.maxFixedHeight);\n };\n\n const setWidth = (refRect: DOMRect, pos: string): number => {\n if (!refRect) return 0;\n\n const _availableWidth =\n pos === 'left' ? window.innerWidth - refRect.left - BODY_PADDING : refRect.right - BODY_PADDING;\n\n return _availableWidth <= MIN_WIDTH ? MIN_WIDTH : _availableWidth;\n };\n\n const setLeft = (refRect: DOMRect, posRect: DOMRect, isMobile: boolean) => {\n if (isMobile) {\n return `${refRect.left - Math.abs(posRect.width - refRect.width) / HALF}px`;\n } else {\n return `${refRect.left}px`;\n }\n };\n\n const calcPosition = (): typeof defaultStyle => {\n const positionedRect = (positionedElement as HTMLElement | null)?.getBoundingClientRect();\n const referenceRect = (referenceElement as HTMLElement | null)?.getBoundingClientRect();\n let yPos = 'bottom';\n let xPos = 'left';\n\n const isMobile = window.matchMedia(\n `(max-width: ${options.mobileBreakpoint ? sizeToPx(options.mobileBreakpoint) : MOBILE_BREAKPOINT}px)`\n ).matches;\n\n if (!referenceRect || !positionedRect) {\n return defaultStyle;\n }\n\n if (window.innerHeight - referenceRect.bottom - BODY_PADDING < MIN_HEIGHT) {\n yPos = 'top';\n }\n\n if (\n (window.innerWidth - referenceRect.left - BODY_PADDING < MIN_WIDTH || options.horizontalPosition === 'right') &&\n !isMobile\n ) {\n xPos = 'right';\n }\n\n return {\n inset: `${yPos === 'bottom' ? referenceRect[yPos] + 'px' : 'auto'}\n ${xPos === 'right' ? window.innerWidth - referenceRect[xPos] + 'px' : 'auto'}\n ${yPos === 'top' ? window.innerHeight - referenceRect[yPos] + 'px' : 'auto'}\n ${xPos === 'left' ? setLeft(referenceRect, positionedRect, isMobile) : 'auto'}`,\n maxHeight: `${setHeight(referenceRect, yPos)}px`,\n maxWidth: `${setWidth(referenceRect, xPos)}px`,\n minWidth: options.fullWidth ? referenceRect.width : MIN_WIDTH,\n overflowX: 'hidden',\n overflowY: 'auto',\n opacity: 1,\n margin: `${options.offset}px 0`,\n };\n };\n\n const handleMouseEvent = (): void => {\n setStyle({\n ...style,\n ...calcPosition(),\n });\n setStatus(true);\n };\n\n const updatePosition = (): void => {\n if (status) {\n setStyle({\n ...style,\n ...calcPosition(),\n });\n }\n };\n\n const handleClickOutside = (evt: Event): void => {\n if (\n !referenceElement ||\n (referenceElement as unknown as HTMLElement).contains(evt.target as Node) ||\n !positionedElement ||\n (positionedElement as unknown as HTMLElement).contains(evt.target as Node)\n ) {\n return;\n }\n };\n\n const debouncedUpdatePosition = useDebounce(updatePosition, DEBOUNCE_DELAY);\n\n useEffect(() => {\n if (referenceElement !== null) {\n if (options.mouseEvent === 'click') {\n // eslint-disable-next-line no-extra-semi\n (referenceElement as unknown as HTMLElement).addEventListener('click', handleMouseEvent);\n } else {\n // eslint-disable-next-line no-extra-semi\n (referenceElement as unknown as HTMLElement).addEventListener('mouseenter', handleMouseEvent);\n // eslint-disable-next-line no-extra-semi\n (referenceElement as unknown as HTMLElement).addEventListener('mouseleave', handleClickOutside);\n }\n document.addEventListener('mousedown', handleClickOutside);\n document.addEventListener('touchstart', handleClickOutside);\n window.addEventListener('resize', debouncedUpdatePosition);\n }\n\n return () => {\n if (referenceElement !== null) {\n if (options.mouseEvent === 'click') {\n // eslint-disable-next-line no-extra-semi\n (referenceElement as unknown as HTMLElement).removeEventListener('click', handleMouseEvent);\n } else {\n // eslint-disable-next-line no-extra-semi\n (referenceElement as unknown as HTMLElement).removeEventListener('mouseenter', handleMouseEvent);\n // eslint-disable-next-line no-extra-semi\n (referenceElement as unknown as HTMLElement).removeEventListener('mouseleave', handleClickOutside);\n }\n document.removeEventListener('mousedown', handleClickOutside);\n document.removeEventListener('touchstart', handleClickOutside);\n window.removeEventListener('resize', debouncedUpdatePosition);\n }\n };\n });\n\n return {\n style: {\n style,\n },\n status,\n updatePosition,\n };\n}\n"],"names":["BODY_PADDING","MIN_HEIGHT","MIN_WIDTH","DEBOUNCE_DELAY","MOBILE_BREAKPOINT","HALF","usePositionedFloaters","positionedElement","referenceElement","options","status","setStatus","useState","defaultStyle","style","setStyle","sizeToPx","size","rootFontSize","setHeight","refRect","pos","_maxHeight","setWidth","_availableWidth","setLeft","posRect","isMobile","calcPosition","positionedRect","referenceRect","yPos","xPos","handleMouseEvent","updatePosition","handleClickOutside","evt","debouncedUpdatePosition","useDebounce","useEffect"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@uva-glass/component-library",
|
|
3
3
|
"author": "Team Glass - Frontend vrienden",
|
|
4
4
|
"private": false,
|
|
5
|
-
"version": "3.34.
|
|
5
|
+
"version": "3.34.8",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "dist/index.js",
|
|
8
8
|
"types": "dist/index.d.ts",
|
|
@@ -52,15 +52,15 @@
|
|
|
52
52
|
"@semantic-release/git": "^10.0.1",
|
|
53
53
|
"@semantic-release/gitlab": "^13.2.6",
|
|
54
54
|
"@semantic-release/npm": "^12.0.2",
|
|
55
|
-
"@storybook/addon-a11y": "^9.0.
|
|
56
|
-
"@storybook/addon-docs": "^9.0.
|
|
57
|
-
"@storybook/addon-links": "^9.0.
|
|
58
|
-
"@storybook/react": "^9.0.
|
|
59
|
-
"@storybook/react-vite": "^9.0.
|
|
55
|
+
"@storybook/addon-a11y": "^9.0.17",
|
|
56
|
+
"@storybook/addon-docs": "^9.0.17",
|
|
57
|
+
"@storybook/addon-links": "^9.0.17",
|
|
58
|
+
"@storybook/react": "^9.0.17",
|
|
59
|
+
"@storybook/react-vite": "^9.0.17",
|
|
60
60
|
"@testing-library/jest-dom": "^6.6.3",
|
|
61
61
|
"@testing-library/react": "^16.3.0",
|
|
62
62
|
"@types/jest": "^30.0.0",
|
|
63
|
-
"@types/node": "^22.16.
|
|
63
|
+
"@types/node": "^22.16.4",
|
|
64
64
|
"@types/react": "^19.1.8",
|
|
65
65
|
"@types/react-dom": "^19.1.6",
|
|
66
66
|
"@uva-glass/eslint-config": "^1.3.11",
|
|
@@ -80,9 +80,9 @@
|
|
|
80
80
|
"npm-run-all2": "^8.0.4",
|
|
81
81
|
"react": "^19.1.0",
|
|
82
82
|
"react-dom": "^19.1.0",
|
|
83
|
-
"react-router": "^7.
|
|
83
|
+
"react-router": "^7.7.0",
|
|
84
84
|
"semantic-release": "^24.2.7",
|
|
85
|
-
"storybook": "^9.0.
|
|
85
|
+
"storybook": "^9.0.17",
|
|
86
86
|
"style-dictionary": "^5.0.1",
|
|
87
87
|
"stylelint": "^16.21.1",
|
|
88
88
|
"stylelint-config-recommended": "^16.0.0",
|
|
@@ -90,7 +90,7 @@
|
|
|
90
90
|
"stylelint-order": "^7.0.0",
|
|
91
91
|
"ts-node": "^10.9.2",
|
|
92
92
|
"typescript": "^5.8.3",
|
|
93
|
-
"vite": "^7.0.
|
|
93
|
+
"vite": "^7.0.5",
|
|
94
94
|
"vite-plugin-dts": "^4.5.4",
|
|
95
95
|
"vite-plugin-lib-inject-css": "^2.2.2",
|
|
96
96
|
"vite-plugin-static-copy": "^3.1.1",
|
|
@@ -109,8 +109,8 @@
|
|
|
109
109
|
},
|
|
110
110
|
"optionalDependencies": {
|
|
111
111
|
"@ast-grep/napi-linux-x64-gnu": "0.38.7",
|
|
112
|
-
"@rollup/rollup-linux-x64-gnu": "^4.45.
|
|
113
|
-
"@rspack/binding-darwin-arm64": "1.4.
|
|
114
|
-
"@rspack/binding-linux-x64-gnu": "1.4.
|
|
112
|
+
"@rollup/rollup-linux-x64-gnu": "^4.45.1",
|
|
113
|
+
"@rspack/binding-darwin-arm64": "1.4.8",
|
|
114
|
+
"@rspack/binding-linux-x64-gnu": "1.4.8"
|
|
115
115
|
}
|
|
116
116
|
}
|