@portnet/ui 6.0.1 → 6.0.2
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/CHANGELOG.md +85 -0
- package/dist/esm/index.js +18 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/v2/__tests__/FieldError.test.js +0 -1
- package/dist/esm/v2/__tests__/FieldError.test.js.map +1 -1
- package/dist/esm/v2/__tests__/FieldWidth.test.js +146 -0
- package/dist/esm/v2/__tests__/FieldWidth.test.js.map +1 -0
- package/dist/esm/v2/__tests__/FileCard.test.js +0 -1
- package/dist/esm/v2/__tests__/FileCard.test.js.map +1 -1
- package/dist/esm/v2/__tests__/FormikCheckbox.test.js +265 -0
- package/dist/esm/v2/__tests__/FormikCheckbox.test.js.map +1 -0
- package/dist/esm/v2/__tests__/FormikDateTimePicker.test.js +248 -0
- package/dist/esm/v2/__tests__/FormikDateTimePicker.test.js.map +1 -0
- package/dist/esm/v2/__tests__/FormikRadioGroup.test.js +380 -0
- package/dist/esm/v2/__tests__/FormikRadioGroup.test.js.map +1 -0
- package/dist/esm/v2/__tests__/MobileRowCard.test.js +0 -1
- package/dist/esm/v2/__tests__/MobileRowCard.test.js.map +1 -1
- package/dist/esm/v2/__tests__/SectionErrorBoundary.test.js.map +1 -1
- package/dist/esm/v2/__tests__/labels-merge.test.js +0 -1
- package/dist/esm/v2/__tests__/labels-merge.test.js.map +1 -1
- package/dist/esm/v2/components/DateTimePicker.js +37 -4
- package/dist/esm/v2/components/DateTimePicker.js.map +1 -1
- package/dist/esm/v2/components/Field.js +63 -1
- package/dist/esm/v2/components/Field.js.map +1 -1
- package/dist/esm/v2/components/index.js +27 -0
- package/dist/esm/v2/components/index.js.map +1 -1
- package/dist/esm/v2/index.js +12 -1
- package/dist/esm/v2/index.js.map +1 -1
- package/dist/esm/v2/patterns/FavoriteColumn.js +14 -61
- package/dist/esm/v2/patterns/FavoriteColumn.js.map +1 -1
- package/dist/esm/v2/patterns/FormikCheckbox.js +140 -0
- package/dist/esm/v2/patterns/FormikCheckbox.js.map +1 -0
- package/dist/esm/v2/patterns/FormikCombobox.js +5 -2
- package/dist/esm/v2/patterns/FormikCombobox.js.map +1 -1
- package/dist/esm/v2/patterns/FormikDatePicker.js +13 -47
- package/dist/esm/v2/patterns/FormikDatePicker.js.map +1 -1
- package/dist/esm/v2/patterns/FormikDateTimePicker.js +150 -0
- package/dist/esm/v2/patterns/FormikDateTimePicker.js.map +1 -0
- package/dist/esm/v2/patterns/FormikInput.js +5 -2
- package/dist/esm/v2/patterns/FormikInput.js.map +1 -1
- package/dist/esm/v2/patterns/FormikRadioGroup.js +141 -0
- package/dist/esm/v2/patterns/FormikRadioGroup.js.map +1 -0
- package/dist/esm/v2/patterns/FormikSelect.js +5 -2
- package/dist/esm/v2/patterns/FormikSelect.js.map +1 -1
- package/dist/esm/v2/patterns/FormikTextarea.js +5 -2
- package/dist/esm/v2/patterns/FormikTextarea.js.map +1 -1
- package/dist/esm/v2/patterns/KeyboardShortcutsHelp.js +25 -8
- package/dist/esm/v2/patterns/KeyboardShortcutsHelp.js.map +1 -1
- package/dist/esm/v2/patterns/RowFavoriteToggle.js +122 -0
- package/dist/esm/v2/patterns/RowFavoriteToggle.js.map +1 -0
- package/dist/esm/v2/patterns/_pickerSerialisation.js +74 -0
- package/dist/esm/v2/patterns/_pickerSerialisation.js.map +1 -0
- package/dist/esm/v2/patterns/index.js +83 -0
- package/dist/esm/v2/patterns/index.js.map +1 -1
- package/dist/esm/v2/personalization/capabilities/gridPreferences.js +209 -0
- package/dist/esm/v2/personalization/capabilities/gridPreferences.js.map +1 -0
- package/dist/esm/v2/personalization/capabilities/index.js +5 -0
- package/dist/esm/v2/personalization/capabilities/index.js.map +1 -1
- package/dist/esm/v2/personalization/index.js +18 -0
- package/dist/esm/v2/personalization/index.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -1
- package/dist/v2/__tests__/FieldError.test.js +26 -30
- package/dist/v2/__tests__/FieldError.test.js.map +1 -1
- package/dist/v2/__tests__/FieldWidth.test.js +150 -0
- package/dist/v2/__tests__/FieldWidth.test.js.map +1 -0
- package/dist/v2/__tests__/FileCard.test.js +25 -29
- package/dist/v2/__tests__/FileCard.test.js.map +1 -1
- package/dist/v2/__tests__/FormikCheckbox.test.js +268 -0
- package/dist/v2/__tests__/FormikCheckbox.test.js.map +1 -0
- package/dist/v2/__tests__/FormikDateTimePicker.test.js +247 -0
- package/dist/v2/__tests__/FormikDateTimePicker.test.js.map +1 -0
- package/dist/v2/__tests__/FormikRadioGroup.test.js +381 -0
- package/dist/v2/__tests__/FormikRadioGroup.test.js.map +1 -0
- package/dist/v2/__tests__/MobileRowCard.test.js +52 -56
- package/dist/v2/__tests__/MobileRowCard.test.js.map +1 -1
- package/dist/v2/__tests__/SectionErrorBoundary.test.js.map +1 -1
- package/dist/v2/__tests__/labels-merge.test.js +20 -24
- package/dist/v2/__tests__/labels-merge.test.js.map +1 -1
- package/dist/v2/components/DateTimePicker.d.ts.map +1 -1
- package/dist/v2/components/DateTimePicker.js +37 -4
- package/dist/v2/components/DateTimePicker.js.map +1 -1
- package/dist/v2/components/Field.d.ts +59 -1
- package/dist/v2/components/Field.d.ts.map +1 -1
- package/dist/v2/components/Field.js +62 -2
- package/dist/v2/components/Field.js.map +1 -1
- package/dist/v2/components/index.d.ts +27 -0
- package/dist/v2/components/index.d.ts.map +1 -1
- package/dist/v2/components/index.js.map +1 -1
- package/dist/v2/index.d.ts.map +1 -1
- package/dist/v2/index.js.map +1 -1
- package/dist/v2/patterns/FavoriteColumn.d.ts +9 -9
- package/dist/v2/patterns/FavoriteColumn.d.ts.map +1 -1
- package/dist/v2/patterns/FavoriteColumn.js +14 -61
- package/dist/v2/patterns/FavoriteColumn.js.map +1 -1
- package/dist/v2/patterns/FormikCheckbox.d.ts +77 -0
- package/dist/v2/patterns/FormikCheckbox.d.ts.map +1 -0
- package/dist/v2/patterns/FormikCheckbox.js +147 -0
- package/dist/v2/patterns/FormikCheckbox.js.map +1 -0
- package/dist/v2/patterns/FormikCombobox.d.ts +7 -1
- package/dist/v2/patterns/FormikCombobox.d.ts.map +1 -1
- package/dist/v2/patterns/FormikCombobox.js +5 -2
- package/dist/v2/patterns/FormikCombobox.js.map +1 -1
- package/dist/v2/patterns/FormikDatePicker.d.ts +13 -1
- package/dist/v2/patterns/FormikDatePicker.d.ts.map +1 -1
- package/dist/v2/patterns/FormikDatePicker.js +33 -66
- package/dist/v2/patterns/FormikDatePicker.js.map +1 -1
- package/dist/v2/patterns/FormikDateTimePicker.d.ts +111 -0
- package/dist/v2/patterns/FormikDateTimePicker.d.ts.map +1 -0
- package/dist/v2/patterns/FormikDateTimePicker.js +158 -0
- package/dist/v2/patterns/FormikDateTimePicker.js.map +1 -0
- package/dist/v2/patterns/FormikInput.d.ts +11 -1
- package/dist/v2/patterns/FormikInput.d.ts.map +1 -1
- package/dist/v2/patterns/FormikInput.js +5 -2
- package/dist/v2/patterns/FormikInput.js.map +1 -1
- package/dist/v2/patterns/FormikRadioGroup.d.ts +80 -0
- package/dist/v2/patterns/FormikRadioGroup.d.ts.map +1 -0
- package/dist/v2/patterns/FormikRadioGroup.js +148 -0
- package/dist/v2/patterns/FormikRadioGroup.js.map +1 -0
- package/dist/v2/patterns/FormikSelect.d.ts +9 -1
- package/dist/v2/patterns/FormikSelect.d.ts.map +1 -1
- package/dist/v2/patterns/FormikSelect.js +5 -2
- package/dist/v2/patterns/FormikSelect.js.map +1 -1
- package/dist/v2/patterns/FormikTextarea.d.ts +9 -1
- package/dist/v2/patterns/FormikTextarea.d.ts.map +1 -1
- package/dist/v2/patterns/FormikTextarea.js +5 -2
- package/dist/v2/patterns/FormikTextarea.js.map +1 -1
- package/dist/v2/patterns/KeyboardShortcutsHelp.d.ts +14 -1
- package/dist/v2/patterns/KeyboardShortcutsHelp.d.ts.map +1 -1
- package/dist/v2/patterns/KeyboardShortcutsHelp.js +25 -8
- package/dist/v2/patterns/KeyboardShortcutsHelp.js.map +1 -1
- package/dist/v2/patterns/RowFavoriteToggle.d.ts +92 -0
- package/dist/v2/patterns/RowFavoriteToggle.d.ts.map +1 -0
- package/dist/v2/patterns/RowFavoriteToggle.js +127 -0
- package/dist/v2/patterns/RowFavoriteToggle.js.map +1 -0
- package/dist/v2/patterns/_pickerSerialisation.d.ts +44 -0
- package/dist/v2/patterns/_pickerSerialisation.d.ts.map +1 -0
- package/dist/v2/patterns/_pickerSerialisation.js +81 -0
- package/dist/v2/patterns/_pickerSerialisation.js.map +1 -0
- package/dist/v2/patterns/index.d.ts +87 -0
- package/dist/v2/patterns/index.d.ts.map +1 -1
- package/dist/v2/patterns/index.js +34 -0
- package/dist/v2/patterns/index.js.map +1 -1
- package/dist/v2/personalization/capabilities/gridPreferences.d.ts +100 -0
- package/dist/v2/personalization/capabilities/gridPreferences.d.ts.map +1 -0
- package/dist/v2/personalization/capabilities/gridPreferences.js +215 -0
- package/dist/v2/personalization/capabilities/gridPreferences.js.map +1 -0
- package/dist/v2/personalization/capabilities/index.d.ts +6 -0
- package/dist/v2/personalization/capabilities/index.d.ts.map +1 -1
- package/dist/v2/personalization/capabilities/index.js +13 -0
- package/dist/v2/personalization/capabilities/index.js.map +1 -1
- package/dist/v2/personalization/index.d.ts +18 -0
- package/dist/v2/personalization/index.d.ts.map +1 -1
- package/dist/v2/personalization/index.js +13 -0
- package/dist/v2/personalization/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -120,12 +120,31 @@ function KeyboardShortcutsHelp(_ref2) {
|
|
|
120
120
|
shortcuts = _ref2$shortcuts === void 0 ? [] : _ref2$shortcuts,
|
|
121
121
|
_ref2$title = _ref2.title,
|
|
122
122
|
title = _ref2$title === void 0 ? "Raccourcis clavier" : _ref2$title,
|
|
123
|
-
labels = _ref2.labels
|
|
123
|
+
labels = _ref2.labels,
|
|
124
|
+
open = _ref2.open,
|
|
125
|
+
onOpenChange = _ref2.onOpenChange;
|
|
124
126
|
var _React$useState = React.useState(false),
|
|
125
127
|
_React$useState2 = _slicedToArray(_React$useState, 2),
|
|
126
|
-
|
|
127
|
-
|
|
128
|
+
uncontrolledOpen = _React$useState2[0],
|
|
129
|
+
setUncontrolledOpen = _React$useState2[1];
|
|
130
|
+
var isControlled = open !== undefined;
|
|
131
|
+
var isOpen = isControlled ? open : uncontrolledOpen;
|
|
128
132
|
var L = (0, _mergeLabels.mergeLabels)(DEFAULT_LABELS, labels);
|
|
133
|
+
|
|
134
|
+
/* Refs so the "?" listener can stay on a `[]` dependency list — it must not
|
|
135
|
+
* be torn down and re-added on every open/close, and in controlled mode there
|
|
136
|
+
* is no functional-update form to fall back on. */
|
|
137
|
+
var isOpenRef = React.useRef(isOpen);
|
|
138
|
+
isOpenRef.current = isOpen;
|
|
139
|
+
var onOpenChangeRef = React.useRef(onOpenChange);
|
|
140
|
+
onOpenChangeRef.current = onOpenChange;
|
|
141
|
+
var isControlledRef = React.useRef(isControlled);
|
|
142
|
+
isControlledRef.current = isControlled;
|
|
143
|
+
var requestOpen = React.useCallback(function (next) {
|
|
144
|
+
var _onOpenChangeRef$curr;
|
|
145
|
+
if (!isControlledRef.current) setUncontrolledOpen(next);
|
|
146
|
+
(_onOpenChangeRef$curr = onOpenChangeRef.current) === null || _onOpenChangeRef$curr === void 0 ? void 0 : _onOpenChangeRef$curr.call(onOpenChangeRef, next);
|
|
147
|
+
}, []);
|
|
129
148
|
React.useEffect(function () {
|
|
130
149
|
var handler = function handler(event) {
|
|
131
150
|
// Only react to "?" (Shift+/ on US, AltGr+, on many AZERTY layouts).
|
|
@@ -138,15 +157,13 @@ function KeyboardShortcutsHelp(_ref2) {
|
|
|
138
157
|
// User is typing in a text field — let "?" through.
|
|
139
158
|
if (isFocusOnTextEntry()) return;
|
|
140
159
|
event.preventDefault();
|
|
141
|
-
|
|
142
|
-
return !prev;
|
|
143
|
-
});
|
|
160
|
+
requestOpen(!isOpenRef.current);
|
|
144
161
|
};
|
|
145
162
|
window.addEventListener("keydown", handler);
|
|
146
163
|
return function () {
|
|
147
164
|
return window.removeEventListener("keydown", handler);
|
|
148
165
|
};
|
|
149
|
-
}, []);
|
|
166
|
+
}, [requestOpen]);
|
|
150
167
|
if (!Array.isArray(shortcuts) || shortcuts.length === 0) {
|
|
151
168
|
return null;
|
|
152
169
|
}
|
|
@@ -154,7 +171,7 @@ function KeyboardShortcutsHelp(_ref2) {
|
|
|
154
171
|
open: isOpen,
|
|
155
172
|
title: title,
|
|
156
173
|
onClose: function onClose() {
|
|
157
|
-
return
|
|
174
|
+
return requestOpen(false);
|
|
158
175
|
},
|
|
159
176
|
size: "md",
|
|
160
177
|
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("dl", {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"KeyboardShortcutsHelp.js","names":["React","_interopRequireWildcard","require","_Modal","_interopRequireDefault","_mergeLabels","_jsxRuntime","obj","__esModule","_getRequireWildcardCache","nodeInterop","WeakMap","cacheBabelInterop","cacheNodeInterop","_typeof","cache","has","get","newObj","hasPropertyDescriptor","Object","defineProperty","getOwnPropertyDescriptor","key","prototype","hasOwnProperty","call","desc","set","_slicedToArray","arr","i","_arrayWithHoles","_iterableToArrayLimit","_unsupportedIterableToArray","_nonIterableRest","TypeError","o","minLen","_arrayLikeToArray","n","toString","slice","constructor","name","Array","from","test","len","length","arr2","_i","Symbol","iterator","_s","_e","_x","_r","_arr","_n","_d","next","done","push","value","err","isArray","isFocusOnTextEntry","el","document","activeElement","tag","tagName","HTMLElement","isContentEditable","ShortcutKey","_ref","children","jsx","style","display","minWidth","padding","background","border","borderBottomColor","borderRadius","boxShadow","fontFamily","fontSize","textAlign","lineHeight","color","SHORTCUT_ROW_SX","gridTemplateColumns","gap","alignItems","borderBottom","SHORTCUT_KEYS_SX","flexWrap","HELP_FOOTNOTE_SX","marginTop","paddingTop","borderTop","DEFAULT_LABELS","freeze","footnoteIntro","footnoteOutro","listAriaLabel","keyJoiner","KeyboardShortcutsHelp","_ref2","_ref2$shortcuts","shortcuts","_ref2$title","title","labels","_React$useState","useState","_React$useState2","isOpen","setIsOpen","L","mergeLabels","useEffect","handler","event","ctrlKey","metaKey","altKey","preventDefault","prev","window","addEventListener","removeEventListener","jsxs","open","onClose","size","margin","map","sc","keys","k","j","Fragment","description","_default","exports"],"sources":["../../../src/lib/v2/patterns/KeyboardShortcutsHelp.tsx"],"sourcesContent":["import * as React from \"react\";\r\nimport Modal from \"../components/Modal\";\r\nimport { mergeLabels } from \"../utils/mergeLabels\";\r\n\r\n/* ── Body-only focus guard ────────────────────────────────────────\r\n * The \"?\" key is a printable character. If a user types \"?\" inside an\r\n * Input / Textarea / contentEditable element we must NOT hijack the\r\n * keypress to open the help — they're trying to type a question mark.\r\n *\r\n * BUTTON / A focus is NOT blocking by design: when the user has tabbed\r\n * onto an interactive non-text element, hitting \"?\" makes sense as a\r\n * help affordance (navigation mode, not text-entry mode).\r\n */\r\nfunction isFocusOnTextEntry(): boolean {\r\n const el = typeof document !== \"undefined\" ? document.activeElement : null;\r\n if (!el) return false;\r\n const tag = el.tagName;\r\n if (tag === \"INPUT\" || tag === \"TEXTAREA\" || tag === \"SELECT\") return true;\r\n if (el instanceof HTMLElement && el.isContentEditable) return true;\r\n return false;\r\n}\r\n\r\nfunction ShortcutKey({ children }: { children?: React.ReactNode }) {\r\n return (\r\n <kbd\r\n style={{\r\n display: \"inline-block\",\r\n minWidth: \"1.75em\",\r\n padding: \"0.15em 0.5em\",\r\n background: \"var(--bg-subtle)\",\r\n border: \"1px solid var(--border)\",\r\n borderBottomColor: \"var(--border-strong, var(--border))\",\r\n borderRadius: \"var(--r-sm)\",\r\n boxShadow: \"inset 0 -1px 0 var(--border)\",\r\n fontFamily: \"var(--font-mono, monospace)\",\r\n fontSize: \"var(--text-sm)\",\r\n textAlign: \"center\",\r\n lineHeight: 1.4,\r\n color: \"var(--fg)\",\r\n }}\r\n >\r\n {children}\r\n </kbd>\r\n );\r\n}\r\n\r\nconst SHORTCUT_ROW_SX: React.CSSProperties = {\r\n display: \"grid\",\r\n gridTemplateColumns: \"auto 1fr\",\r\n gap: \"var(--s-4)\",\r\n alignItems: \"center\",\r\n padding: \"var(--s-2) 0\",\r\n borderBottom: \"1px solid var(--border-subtle, var(--border))\",\r\n};\r\n\r\nconst SHORTCUT_KEYS_SX: React.CSSProperties = {\r\n display: \"flex\",\r\n gap: \"var(--s-1)\",\r\n alignItems: \"center\",\r\n flexWrap: \"wrap\",\r\n};\r\n\r\nconst HELP_FOOTNOTE_SX: React.CSSProperties = {\r\n marginTop: \"var(--s-4)\",\r\n paddingTop: \"var(--s-3)\",\r\n borderTop: \"1px solid var(--border)\",\r\n fontSize: \"var(--text-xs)\",\r\n color: \"var(--fg-subtle)\",\r\n lineHeight: 1.5,\r\n};\r\n\r\nconst DEFAULT_LABELS = Object.freeze({\r\n /* Footnote rendered below the shortcut list. Split into two parts so the\r\n * keycap can be embedded in the middle without forcing the i18n string to\r\n * carry HTML tags. */\r\n footnoteIntro: \"Astuce : appuyez sur\",\r\n footnoteOutro:\r\n \"à tout moment pour ouvrir ou fermer cette aide. Les raccourcis s'activent uniquement quand votre curseur n'est pas dans un champ de saisie.\",\r\n /* aria-label on the <dl> listing every shortcut. */\r\n listAriaLabel: \"Liste des raccourcis clavier disponibles sur cette page\",\r\n /* Joiner rendered between alternative keys for the same shortcut. */\r\n keyJoiner: \"ou\",\r\n});\r\n\r\n/**\r\n * KeyboardShortcutsHelp — Portnet UI v2\r\n *\r\n * Charter §5.2 SHOULD — discoverable help overlay for page-level keyboard\r\n * shortcuts. Listens globally for \"?\" and opens a v2.Modal listing every\r\n * shortcut as <kbd> elements (WCAG 1.3.1 semantic).\r\n *\r\n * Self-contained: the host page only declares the shortcuts array and renders\r\n * <KeyboardShortcutsHelp shortcuts={…} /> once.\r\n *\r\n * Localisation (FR / EN / AR):\r\n * <KeyboardShortcutsHelp\r\n * title=\"Keyboard shortcuts\"\r\n * labels={{\r\n * footnoteIntro: \"Tip: press\",\r\n * footnoteOutro: \"anytime to toggle this help…\",\r\n * listAriaLabel: \"List of keyboard shortcuts available on this page\",\r\n * keyJoiner: \"or\",\r\n * }}\r\n * shortcuts={…}\r\n * />\r\n *\r\n * Charter §5.2 SHOULD + WCAG 1.3.1 (semantic <kbd>) + 2.1.1 (keyboard\r\n * reachable) + R-M.* (modal focus trap inherited from v2.Modal).\r\n */\r\n\r\nexport interface KeyboardShortcut {\r\n keys: string[];\r\n description: React.ReactNode;\r\n}\r\n\r\nexport interface KeyboardShortcutsHelpLabels {\r\n footnoteIntro?: string | undefined;\r\n footnoteOutro?: string | undefined;\r\n listAriaLabel?: string | undefined;\r\n keyJoiner?: string | undefined;\r\n}\r\n\r\nexport interface KeyboardShortcutsHelpProps {\r\n shortcuts?: KeyboardShortcut[] | undefined;\r\n title?: React.ReactNode | undefined;\r\n labels?: KeyboardShortcutsHelpLabels | undefined;\r\n}\r\n\r\nfunction KeyboardShortcutsHelp({\r\n shortcuts = [],\r\n title = \"Raccourcis clavier\",\r\n labels,\r\n}: KeyboardShortcutsHelpProps) {\r\n const [isOpen, setIsOpen] = React.useState(false);\r\n const L = mergeLabels(DEFAULT_LABELS, labels);\r\n\r\n React.useEffect(() => {\r\n const handler = (event: KeyboardEvent) => {\r\n // Only react to \"?\" (Shift+/ on US, AltGr+, on many AZERTY layouts).\r\n // event.key gives us the resolved character regardless of physical key.\r\n if (event.key !== \"?\") return;\r\n\r\n // Modifier keys (Ctrl, Meta, Alt) reserved for browser / OS shortcuts.\r\n if (event.ctrlKey || event.metaKey || event.altKey) return;\r\n\r\n // User is typing in a text field — let \"?\" through.\r\n if (isFocusOnTextEntry()) return;\r\n\r\n event.preventDefault();\r\n setIsOpen((prev) => !prev);\r\n };\r\n\r\n window.addEventListener(\"keydown\", handler);\r\n return () => window.removeEventListener(\"keydown\", handler);\r\n }, []);\r\n\r\n if (!Array.isArray(shortcuts) || shortcuts.length === 0) {\r\n return null;\r\n }\r\n\r\n return (\r\n <Modal open={isOpen} title={title} onClose={() => setIsOpen(false)} size=\"md\">\r\n <dl style={{ margin: 0, padding: 0 }} aria-label={L.listAriaLabel}>\r\n {shortcuts.map((sc, i) => (\r\n <div key={i} style={SHORTCUT_ROW_SX}>\r\n <dt style={SHORTCUT_KEYS_SX}>\r\n {sc.keys.map((k, j) => (\r\n <React.Fragment key={j}>\r\n <ShortcutKey>{k}</ShortcutKey>\r\n {j < sc.keys.length - 1 && (\r\n <span\r\n aria-hidden=\"true\"\r\n style={{\r\n color: \"var(--fg-subtle)\",\r\n fontSize: \"var(--text-xs)\",\r\n }}\r\n >\r\n {L.keyJoiner}\r\n </span>\r\n )}\r\n </React.Fragment>\r\n ))}\r\n </dt>\r\n <dd style={{ margin: 0, fontSize: \"var(--text-body)\" }}>\r\n {sc.description}\r\n </dd>\r\n </div>\r\n ))}\r\n </dl>\r\n <div style={HELP_FOOTNOTE_SX}>\r\n {L.footnoteIntro}{\" \"}\r\n <ShortcutKey>?</ShortcutKey>{\" \"}\r\n {L.footnoteOutro}\r\n </div>\r\n </Modal>\r\n );\r\n}\r\n\r\nexport default KeyboardShortcutsHelp;\r\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"KeyboardShortcutsHelp.js","names":["React","_interopRequireWildcard","require","_Modal","_interopRequireDefault","_mergeLabels","_jsxRuntime","obj","__esModule","_getRequireWildcardCache","nodeInterop","WeakMap","cacheBabelInterop","cacheNodeInterop","_typeof","cache","has","get","newObj","hasPropertyDescriptor","Object","defineProperty","getOwnPropertyDescriptor","key","prototype","hasOwnProperty","call","desc","set","_slicedToArray","arr","i","_arrayWithHoles","_iterableToArrayLimit","_unsupportedIterableToArray","_nonIterableRest","TypeError","o","minLen","_arrayLikeToArray","n","toString","slice","constructor","name","Array","from","test","len","length","arr2","_i","Symbol","iterator","_s","_e","_x","_r","_arr","_n","_d","next","done","push","value","err","isArray","isFocusOnTextEntry","el","document","activeElement","tag","tagName","HTMLElement","isContentEditable","ShortcutKey","_ref","children","jsx","style","display","minWidth","padding","background","border","borderBottomColor","borderRadius","boxShadow","fontFamily","fontSize","textAlign","lineHeight","color","SHORTCUT_ROW_SX","gridTemplateColumns","gap","alignItems","borderBottom","SHORTCUT_KEYS_SX","flexWrap","HELP_FOOTNOTE_SX","marginTop","paddingTop","borderTop","DEFAULT_LABELS","freeze","footnoteIntro","footnoteOutro","listAriaLabel","keyJoiner","KeyboardShortcutsHelp","_ref2","_ref2$shortcuts","shortcuts","_ref2$title","title","labels","open","onOpenChange","_React$useState","useState","_React$useState2","uncontrolledOpen","setUncontrolledOpen","isControlled","undefined","isOpen","L","mergeLabels","isOpenRef","useRef","current","onOpenChangeRef","isControlledRef","requestOpen","useCallback","_onOpenChangeRef$curr","useEffect","handler","event","ctrlKey","metaKey","altKey","preventDefault","window","addEventListener","removeEventListener","jsxs","onClose","size","margin","map","sc","keys","k","j","Fragment","description","_default","exports"],"sources":["../../../src/lib/v2/patterns/KeyboardShortcutsHelp.tsx"],"sourcesContent":["import * as React from \"react\";\r\nimport Modal from \"../components/Modal\";\r\nimport { mergeLabels } from \"../utils/mergeLabels\";\r\n\r\n/* ── Body-only focus guard ────────────────────────────────────────\r\n * The \"?\" key is a printable character. If a user types \"?\" inside an\r\n * Input / Textarea / contentEditable element we must NOT hijack the\r\n * keypress to open the help — they're trying to type a question mark.\r\n *\r\n * BUTTON / A focus is NOT blocking by design: when the user has tabbed\r\n * onto an interactive non-text element, hitting \"?\" makes sense as a\r\n * help affordance (navigation mode, not text-entry mode).\r\n */\r\nfunction isFocusOnTextEntry(): boolean {\r\n const el = typeof document !== \"undefined\" ? document.activeElement : null;\r\n if (!el) return false;\r\n const tag = el.tagName;\r\n if (tag === \"INPUT\" || tag === \"TEXTAREA\" || tag === \"SELECT\") return true;\r\n if (el instanceof HTMLElement && el.isContentEditable) return true;\r\n return false;\r\n}\r\n\r\nfunction ShortcutKey({ children }: { children?: React.ReactNode }) {\r\n return (\r\n <kbd\r\n style={{\r\n display: \"inline-block\",\r\n minWidth: \"1.75em\",\r\n padding: \"0.15em 0.5em\",\r\n background: \"var(--bg-subtle)\",\r\n border: \"1px solid var(--border)\",\r\n borderBottomColor: \"var(--border-strong, var(--border))\",\r\n borderRadius: \"var(--r-sm)\",\r\n boxShadow: \"inset 0 -1px 0 var(--border)\",\r\n fontFamily: \"var(--font-mono, monospace)\",\r\n fontSize: \"var(--text-sm)\",\r\n textAlign: \"center\",\r\n lineHeight: 1.4,\r\n color: \"var(--fg)\",\r\n }}\r\n >\r\n {children}\r\n </kbd>\r\n );\r\n}\r\n\r\nconst SHORTCUT_ROW_SX: React.CSSProperties = {\r\n display: \"grid\",\r\n gridTemplateColumns: \"auto 1fr\",\r\n gap: \"var(--s-4)\",\r\n alignItems: \"center\",\r\n padding: \"var(--s-2) 0\",\r\n borderBottom: \"1px solid var(--border-subtle, var(--border))\",\r\n};\r\n\r\nconst SHORTCUT_KEYS_SX: React.CSSProperties = {\r\n display: \"flex\",\r\n gap: \"var(--s-1)\",\r\n alignItems: \"center\",\r\n flexWrap: \"wrap\",\r\n};\r\n\r\nconst HELP_FOOTNOTE_SX: React.CSSProperties = {\r\n marginTop: \"var(--s-4)\",\r\n paddingTop: \"var(--s-3)\",\r\n borderTop: \"1px solid var(--border)\",\r\n fontSize: \"var(--text-xs)\",\r\n color: \"var(--fg-subtle)\",\r\n lineHeight: 1.5,\r\n};\r\n\r\nconst DEFAULT_LABELS = Object.freeze({\r\n /* Footnote rendered below the shortcut list. Split into two parts so the\r\n * keycap can be embedded in the middle without forcing the i18n string to\r\n * carry HTML tags. */\r\n footnoteIntro: \"Astuce : appuyez sur\",\r\n footnoteOutro:\r\n \"à tout moment pour ouvrir ou fermer cette aide. Les raccourcis s'activent uniquement quand votre curseur n'est pas dans un champ de saisie.\",\r\n /* aria-label on the <dl> listing every shortcut. */\r\n listAriaLabel: \"Liste des raccourcis clavier disponibles sur cette page\",\r\n /* Joiner rendered between alternative keys for the same shortcut. */\r\n keyJoiner: \"ou\",\r\n});\r\n\r\n/**\r\n * KeyboardShortcutsHelp — Portnet UI v2\r\n *\r\n * Charter §5.2 SHOULD — discoverable help overlay for page-level keyboard\r\n * shortcuts. Listens globally for \"?\" and opens a v2.Modal listing every\r\n * shortcut as <kbd> elements (WCAG 1.3.1 semantic).\r\n *\r\n * Self-contained: the host page only declares the shortcuts array and renders\r\n * <KeyboardShortcutsHelp shortcuts={…} /> once.\r\n *\r\n * Localisation (FR / EN / AR):\r\n * <KeyboardShortcutsHelp\r\n * title=\"Keyboard shortcuts\"\r\n * labels={{\r\n * footnoteIntro: \"Tip: press\",\r\n * footnoteOutro: \"anytime to toggle this help…\",\r\n * listAriaLabel: \"List of keyboard shortcuts available on this page\",\r\n * keyJoiner: \"or\",\r\n * }}\r\n * shortcuts={…}\r\n * />\r\n *\r\n * Charter §5.2 SHOULD + WCAG 1.3.1 (semantic <kbd>) + 2.1.1 (keyboard\r\n * reachable) + R-M.* (modal focus trap inherited from v2.Modal).\r\n */\r\n\r\nexport interface KeyboardShortcut {\r\n keys: string[];\r\n description: React.ReactNode;\r\n}\r\n\r\nexport interface KeyboardShortcutsHelpLabels {\r\n footnoteIntro?: string | undefined;\r\n footnoteOutro?: string | undefined;\r\n listAriaLabel?: string | undefined;\r\n keyJoiner?: string | undefined;\r\n}\r\n\r\nexport interface KeyboardShortcutsHelpProps {\r\n shortcuts?: KeyboardShortcut[] | undefined;\r\n title?: React.ReactNode | undefined;\r\n labels?: KeyboardShortcutsHelpLabels | undefined;\r\n /**\r\n * Optional CONTROLLED open state. Omit for the original self-contained\r\n * behaviour (the \"?\" listener owns the state).\r\n *\r\n * Added because the panel had no trigger but the keystroke. Hosts wired it\r\n * correctly and users still reported the shortcuts \"missing\" — they are, in\r\n * every practical sense, if the only affordance is a key you have to already\r\n * know about. Charter §05.2 asks for DISCOVERABLE help, and a host cannot add\r\n * a menu item or button without being able to open this.\r\n */\r\n open?: boolean | undefined;\r\n /** Called with the requested next state, for both \"?\" and the close button. */\r\n onOpenChange?: ((open: boolean) => void) | undefined;\r\n}\r\n\r\nfunction KeyboardShortcutsHelp({\r\n shortcuts = [],\r\n title = \"Raccourcis clavier\",\r\n labels,\r\n open,\r\n onOpenChange,\r\n}: KeyboardShortcutsHelpProps) {\r\n const [uncontrolledOpen, setUncontrolledOpen] = React.useState(false);\r\n const isControlled = open !== undefined;\r\n const isOpen = isControlled ? open : uncontrolledOpen;\r\n const L = mergeLabels(DEFAULT_LABELS, labels);\r\n\r\n /* Refs so the \"?\" listener can stay on a `[]` dependency list — it must not\r\n * be torn down and re-added on every open/close, and in controlled mode there\r\n * is no functional-update form to fall back on. */\r\n const isOpenRef = React.useRef(isOpen);\r\n isOpenRef.current = isOpen;\r\n const onOpenChangeRef = React.useRef(onOpenChange);\r\n onOpenChangeRef.current = onOpenChange;\r\n const isControlledRef = React.useRef(isControlled);\r\n isControlledRef.current = isControlled;\r\n\r\n const requestOpen = React.useCallback((next: boolean) => {\r\n if (!isControlledRef.current) setUncontrolledOpen(next);\r\n onOpenChangeRef.current?.(next);\r\n }, []);\r\n\r\n React.useEffect(() => {\r\n const handler = (event: KeyboardEvent) => {\r\n // Only react to \"?\" (Shift+/ on US, AltGr+, on many AZERTY layouts).\r\n // event.key gives us the resolved character regardless of physical key.\r\n if (event.key !== \"?\") return;\r\n\r\n // Modifier keys (Ctrl, Meta, Alt) reserved for browser / OS shortcuts.\r\n if (event.ctrlKey || event.metaKey || event.altKey) return;\r\n\r\n // User is typing in a text field — let \"?\" through.\r\n if (isFocusOnTextEntry()) return;\r\n\r\n event.preventDefault();\r\n requestOpen(!isOpenRef.current);\r\n };\r\n\r\n window.addEventListener(\"keydown\", handler);\r\n return () => window.removeEventListener(\"keydown\", handler);\r\n }, [requestOpen]);\r\n\r\n if (!Array.isArray(shortcuts) || shortcuts.length === 0) {\r\n return null;\r\n }\r\n\r\n return (\r\n <Modal\r\n open={isOpen}\r\n title={title}\r\n onClose={() => requestOpen(false)}\r\n size=\"md\"\r\n >\r\n <dl style={{ margin: 0, padding: 0 }} aria-label={L.listAriaLabel}>\r\n {shortcuts.map((sc, i) => (\r\n <div key={i} style={SHORTCUT_ROW_SX}>\r\n <dt style={SHORTCUT_KEYS_SX}>\r\n {sc.keys.map((k, j) => (\r\n <React.Fragment key={j}>\r\n <ShortcutKey>{k}</ShortcutKey>\r\n {j < sc.keys.length - 1 && (\r\n <span\r\n aria-hidden=\"true\"\r\n style={{\r\n color: \"var(--fg-subtle)\",\r\n fontSize: \"var(--text-xs)\",\r\n }}\r\n >\r\n {L.keyJoiner}\r\n </span>\r\n )}\r\n </React.Fragment>\r\n ))}\r\n </dt>\r\n <dd style={{ margin: 0, fontSize: \"var(--text-body)\" }}>\r\n {sc.description}\r\n </dd>\r\n </div>\r\n ))}\r\n </dl>\r\n <div style={HELP_FOOTNOTE_SX}>\r\n {L.footnoteIntro}{\" \"}\r\n <ShortcutKey>?</ShortcutKey>{\" \"}\r\n {L.footnoteOutro}\r\n </div>\r\n </Modal>\r\n );\r\n}\r\n\r\nexport default KeyboardShortcutsHelp;\r\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import FavoriteToggle from "../components/FavoriteToggle";
|
|
3
|
+
import type { RowId } from "../types/common";
|
|
4
|
+
/**
|
|
5
|
+
* RowFavoriteToggle — Portnet UI v2 (pattern)
|
|
6
|
+
*
|
|
7
|
+
* A store-connected follow star for ONE row. Reads `useIsFavorite`, renders
|
|
8
|
+
* `FavoriteToggle`, and stops its own click/keydown from reaching the row's
|
|
9
|
+
* `onRowClick`.
|
|
10
|
+
*
|
|
11
|
+
* ─────────────────────────────────────────────────────────────────────────────
|
|
12
|
+
* WHY THIS BELONGS IN THE LIBRARY (capability gap G-36)
|
|
13
|
+
*
|
|
14
|
+
* This exact component already existed — as `FavoriteCell`, private inside
|
|
15
|
+
* `makeFavoriteColumn`. So the follow star was reachable in ONE context only:
|
|
16
|
+
* as a DataGrid column. Every other place a row appears had to rebuild it.
|
|
17
|
+
*
|
|
18
|
+
* The place that always appears is the MOBILE CARD. `DataGrid` swaps to
|
|
19
|
+
* `renderMobileCard` below its `mobileBreakpoint`, and `MobileRowCard` has a
|
|
20
|
+
* `leading` slot precisely for a per-row control — but a column definition
|
|
21
|
+
* cannot be rendered into a slot, so the host had to re-derive the star by
|
|
22
|
+
* hand. Observed in `onssa-export-fe` as a local `MobileFavoriteToggle`, and
|
|
23
|
+
* `ms-ti-fe` destructures the identical `MobileRowCard` + `FavoriteToggle` +
|
|
24
|
+
* `useIsFavorite` trio for the same reason.
|
|
25
|
+
*
|
|
26
|
+
* This is the same failure mode G-10 recorded for the card recipe welded
|
|
27
|
+
* inside `FormSection`: the library owned the behaviour but exposed it at only
|
|
28
|
+
* one composition point, so consumers reimplemented it at the others. And it
|
|
29
|
+
* was not a harmless copy — the local twin drifted on the part that matters
|
|
30
|
+
* least visibly and most to a screen-reader user. It labelled itself
|
|
31
|
+
* "Ajouter aux favoris" / "Retirer des favoris" while the grid column on the
|
|
32
|
+
* SAME page said "Suivre" / "Ne plus suivre", and it omitted the status
|
|
33
|
+
* Tooltip entirely. One list, one control, two accessible names, depending on
|
|
34
|
+
* viewport width — exactly what R-2.1 forbids.
|
|
35
|
+
*
|
|
36
|
+
* `makeFavoriteColumn` now renders this component, so the desktop column and
|
|
37
|
+
* the mobile card are guaranteed to agree by construction rather than by
|
|
38
|
+
* review.
|
|
39
|
+
* ─────────────────────────────────────────────────────────────────────────────
|
|
40
|
+
*
|
|
41
|
+
* Usage — mobile card `leading` slot:
|
|
42
|
+
*
|
|
43
|
+
* <MobileRowCard
|
|
44
|
+
* leading={
|
|
45
|
+
* <RowFavoriteToggle
|
|
46
|
+
* resourceKey="ti:list"
|
|
47
|
+
* rowId={row.reference}
|
|
48
|
+
* rowLabel={row.reference}
|
|
49
|
+
* />
|
|
50
|
+
* }
|
|
51
|
+
* title={row.reference}
|
|
52
|
+
* … />
|
|
53
|
+
*
|
|
54
|
+
* a11y. The accessible name is ACTION-oriented ("Suivre" / "Ne plus suivre",
|
|
55
|
+
* optionally enriched with `rowLabel`) because that is the toggle convention;
|
|
56
|
+
* `aria-pressed` — set by `FavoriteToggle` — carries the state. The visible
|
|
57
|
+
* status ("Suivi" / "Non suivi") is shown as a Tooltip on hover/focus. An
|
|
58
|
+
* `aria-label` is therefore ALWAYS supplied, which also stops Tooltip from
|
|
59
|
+
* mirroring its title onto the trigger and producing a doubled name.
|
|
60
|
+
*
|
|
61
|
+
* Requires a <UserPersonalizationProvider> ancestor (`useIsFavorite` throws
|
|
62
|
+
* otherwise). `rowId` MUST be the same id the grid uses, so the follow and the
|
|
63
|
+
* row agree.
|
|
64
|
+
*/
|
|
65
|
+
/** `FavoriteToggle`'s own size union, re-derived rather than restated. */
|
|
66
|
+
export type FavoriteToggleSize = NonNullable<React.ComponentProps<typeof FavoriteToggle>["size"]>;
|
|
67
|
+
export interface RowFavoriteToggleLabels {
|
|
68
|
+
addFavorite: string;
|
|
69
|
+
removeFavorite: string;
|
|
70
|
+
statusFollowed: string;
|
|
71
|
+
statusNotFollowed: string;
|
|
72
|
+
}
|
|
73
|
+
export declare const DEFAULT_ROW_FAVORITE_LABELS: Readonly<{
|
|
74
|
+
addFavorite: string;
|
|
75
|
+
removeFavorite: string;
|
|
76
|
+
statusFollowed: string;
|
|
77
|
+
statusNotFollowed: string;
|
|
78
|
+
}>;
|
|
79
|
+
export interface RowFavoriteToggleProps {
|
|
80
|
+
/** Follow namespace — must match the list's other personalization calls. */
|
|
81
|
+
resourceKey: string;
|
|
82
|
+
/** Business row id. MUST match the grid's `getRowId` for this row. */
|
|
83
|
+
rowId: RowId;
|
|
84
|
+
/** Enriches the per-row accessible name ("Suivre : 2025-IM-0042"). */
|
|
85
|
+
rowLabel?: string | undefined;
|
|
86
|
+
/** @default "sm" — fits dense rows and card leading slots. */
|
|
87
|
+
size?: FavoriteToggleSize | undefined;
|
|
88
|
+
labels?: Partial<RowFavoriteToggleLabels> | undefined;
|
|
89
|
+
}
|
|
90
|
+
declare function RowFavoriteToggle(props: RowFavoriteToggleProps): React.JSX.Element;
|
|
91
|
+
export default RowFavoriteToggle;
|
|
92
|
+
//# sourceMappingURL=RowFavoriteToggle.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RowFavoriteToggle.d.ts","sourceRoot":"","sources":["../../../src/lib/v2/patterns/RowFavoriteToggle.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,cAAc,MAAM,8BAA8B,CAAC;AAG1D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAE7C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4DG;AAEH,0EAA0E;AAC1E,MAAM,MAAM,kBAAkB,GAAG,WAAW,CAC1C,KAAK,CAAC,cAAc,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CACpD,CAAC;AAEF,MAAM,WAAW,uBAAuB;IACtC,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED,eAAO,MAAM,2BAA2B;;;;;EAKJ,CAAC;AAErC,MAAM,WAAW,sBAAsB;IACrC,4EAA4E;IAC5E,WAAW,EAAE,MAAM,CAAC;IACpB,sEAAsE;IACtE,KAAK,EAAE,KAAK,CAAC;IACb,sEAAsE;IACtE,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,8DAA8D;IAC9D,IAAI,CAAC,EAAE,kBAAkB,GAAG,SAAS,CAAC;IACtC,MAAM,CAAC,EAAE,OAAO,CAAC,uBAAuB,CAAC,GAAG,SAAS,CAAC;CACvD;AAED,iBAAS,iBAAiB,CAAC,KAAK,EAAE,sBAAsB,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CAuC3E;AAED,eAAe,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports["default"] = exports.DEFAULT_ROW_FAVORITE_LABELS = void 0;
|
|
7
|
+
var React = _interopRequireWildcard(require("react"));
|
|
8
|
+
var _FavoriteToggle = _interopRequireDefault(require("../components/FavoriteToggle"));
|
|
9
|
+
var _Tooltip = _interopRequireDefault(require("../components/Tooltip"));
|
|
10
|
+
var _favorites = require("../personalization/capabilities/favorites");
|
|
11
|
+
var _jsxRuntime = require("react/jsx-runtime");
|
|
12
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
|
|
13
|
+
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
|
14
|
+
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { "default": obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj["default"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
|
15
|
+
function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); }
|
|
16
|
+
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
|
|
17
|
+
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
|
|
18
|
+
function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
19
|
+
function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return _typeof(key) === "symbol" ? key : String(key); }
|
|
20
|
+
function _toPrimitive(input, hint) { if (_typeof(input) !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (_typeof(res) !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); } /**
|
|
21
|
+
* RowFavoriteToggle — Portnet UI v2 (pattern)
|
|
22
|
+
*
|
|
23
|
+
* A store-connected follow star for ONE row. Reads `useIsFavorite`, renders
|
|
24
|
+
* `FavoriteToggle`, and stops its own click/keydown from reaching the row's
|
|
25
|
+
* `onRowClick`.
|
|
26
|
+
*
|
|
27
|
+
* ─────────────────────────────────────────────────────────────────────────────
|
|
28
|
+
* WHY THIS BELONGS IN THE LIBRARY (capability gap G-36)
|
|
29
|
+
*
|
|
30
|
+
* This exact component already existed — as `FavoriteCell`, private inside
|
|
31
|
+
* `makeFavoriteColumn`. So the follow star was reachable in ONE context only:
|
|
32
|
+
* as a DataGrid column. Every other place a row appears had to rebuild it.
|
|
33
|
+
*
|
|
34
|
+
* The place that always appears is the MOBILE CARD. `DataGrid` swaps to
|
|
35
|
+
* `renderMobileCard` below its `mobileBreakpoint`, and `MobileRowCard` has a
|
|
36
|
+
* `leading` slot precisely for a per-row control — but a column definition
|
|
37
|
+
* cannot be rendered into a slot, so the host had to re-derive the star by
|
|
38
|
+
* hand. Observed in `onssa-export-fe` as a local `MobileFavoriteToggle`, and
|
|
39
|
+
* `ms-ti-fe` destructures the identical `MobileRowCard` + `FavoriteToggle` +
|
|
40
|
+
* `useIsFavorite` trio for the same reason.
|
|
41
|
+
*
|
|
42
|
+
* This is the same failure mode G-10 recorded for the card recipe welded
|
|
43
|
+
* inside `FormSection`: the library owned the behaviour but exposed it at only
|
|
44
|
+
* one composition point, so consumers reimplemented it at the others. And it
|
|
45
|
+
* was not a harmless copy — the local twin drifted on the part that matters
|
|
46
|
+
* least visibly and most to a screen-reader user. It labelled itself
|
|
47
|
+
* "Ajouter aux favoris" / "Retirer des favoris" while the grid column on the
|
|
48
|
+
* SAME page said "Suivre" / "Ne plus suivre", and it omitted the status
|
|
49
|
+
* Tooltip entirely. One list, one control, two accessible names, depending on
|
|
50
|
+
* viewport width — exactly what R-2.1 forbids.
|
|
51
|
+
*
|
|
52
|
+
* `makeFavoriteColumn` now renders this component, so the desktop column and
|
|
53
|
+
* the mobile card are guaranteed to agree by construction rather than by
|
|
54
|
+
* review.
|
|
55
|
+
* ─────────────────────────────────────────────────────────────────────────────
|
|
56
|
+
*
|
|
57
|
+
* Usage — mobile card `leading` slot:
|
|
58
|
+
*
|
|
59
|
+
* <MobileRowCard
|
|
60
|
+
* leading={
|
|
61
|
+
* <RowFavoriteToggle
|
|
62
|
+
* resourceKey="ti:list"
|
|
63
|
+
* rowId={row.reference}
|
|
64
|
+
* rowLabel={row.reference}
|
|
65
|
+
* />
|
|
66
|
+
* }
|
|
67
|
+
* title={row.reference}
|
|
68
|
+
* … />
|
|
69
|
+
*
|
|
70
|
+
* a11y. The accessible name is ACTION-oriented ("Suivre" / "Ne plus suivre",
|
|
71
|
+
* optionally enriched with `rowLabel`) because that is the toggle convention;
|
|
72
|
+
* `aria-pressed` — set by `FavoriteToggle` — carries the state. The visible
|
|
73
|
+
* status ("Suivi" / "Non suivi") is shown as a Tooltip on hover/focus. An
|
|
74
|
+
* `aria-label` is therefore ALWAYS supplied, which also stops Tooltip from
|
|
75
|
+
* mirroring its title onto the trigger and producing a doubled name.
|
|
76
|
+
*
|
|
77
|
+
* Requires a <UserPersonalizationProvider> ancestor (`useIsFavorite` throws
|
|
78
|
+
* otherwise). `rowId` MUST be the same id the grid uses, so the follow and the
|
|
79
|
+
* row agree.
|
|
80
|
+
*/ /** `FavoriteToggle`'s own size union, re-derived rather than restated. */
|
|
81
|
+
var DEFAULT_ROW_FAVORITE_LABELS = exports.DEFAULT_ROW_FAVORITE_LABELS = Object.freeze({
|
|
82
|
+
addFavorite: "Suivre",
|
|
83
|
+
removeFavorite: "Ne plus suivre",
|
|
84
|
+
statusFollowed: "Suivi",
|
|
85
|
+
statusNotFollowed: "Non suivi"
|
|
86
|
+
});
|
|
87
|
+
function RowFavoriteToggle(props) {
|
|
88
|
+
var resourceKey = props.resourceKey,
|
|
89
|
+
rowId = props.rowId,
|
|
90
|
+
rowLabel = props.rowLabel,
|
|
91
|
+
_props$size = props.size,
|
|
92
|
+
size = _props$size === void 0 ? "sm" : _props$size,
|
|
93
|
+
labels = props.labels;
|
|
94
|
+
var L = labels ? _objectSpread(_objectSpread({}, DEFAULT_ROW_FAVORITE_LABELS), labels) : DEFAULT_ROW_FAVORITE_LABELS;
|
|
95
|
+
var _useIsFavorite = (0, _favorites.useIsFavorite)(resourceKey, rowId),
|
|
96
|
+
isFavorite = _useIsFavorite.isFavorite,
|
|
97
|
+
toggle = _useIsFavorite.toggle;
|
|
98
|
+
var action = isFavorite ? L.removeFavorite : L.addFavorite;
|
|
99
|
+
var ariaLabel = rowLabel ? action + " : " + rowLabel : action;
|
|
100
|
+
var statusLabel = isFavorite ? L.statusFollowed : L.statusNotFollowed;
|
|
101
|
+
var handleChange = function handleChange(_next, e) {
|
|
102
|
+
// Don't let the toggle's click bubble to the row's onRowClick.
|
|
103
|
+
if (e && typeof e.stopPropagation === "function") e.stopPropagation();
|
|
104
|
+
toggle();
|
|
105
|
+
};
|
|
106
|
+
var handleKeyDown = function handleKeyDown(e) {
|
|
107
|
+
// Prevent row-level Enter/Space (onRowClick) from also firing; the
|
|
108
|
+
// button's own native activation is unaffected.
|
|
109
|
+
e.stopPropagation();
|
|
110
|
+
};
|
|
111
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_Tooltip["default"], {
|
|
112
|
+
title: statusLabel,
|
|
113
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_FavoriteToggle["default"], {
|
|
114
|
+
pressed: isFavorite,
|
|
115
|
+
onChange: handleChange,
|
|
116
|
+
onKeyDown: handleKeyDown,
|
|
117
|
+
size: size,
|
|
118
|
+
labels: {
|
|
119
|
+
addFavorite: L.addFavorite,
|
|
120
|
+
removeFavorite: L.removeFavorite
|
|
121
|
+
},
|
|
122
|
+
"aria-label": ariaLabel
|
|
123
|
+
})
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
var _default = exports["default"] = RowFavoriteToggle;
|
|
127
|
+
//# sourceMappingURL=RowFavoriteToggle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RowFavoriteToggle.js","names":["React","_interopRequireWildcard","require","_FavoriteToggle","_interopRequireDefault","_Tooltip","_favorites","_jsxRuntime","obj","__esModule","_getRequireWildcardCache","nodeInterop","WeakMap","cacheBabelInterop","cacheNodeInterop","_typeof","cache","has","get","newObj","hasPropertyDescriptor","Object","defineProperty","getOwnPropertyDescriptor","key","prototype","hasOwnProperty","call","desc","set","Symbol","iterator","constructor","ownKeys","object","enumerableOnly","keys","getOwnPropertySymbols","symbols","filter","sym","enumerable","push","apply","_objectSpread","target","i","arguments","length","source","forEach","_defineProperty","getOwnPropertyDescriptors","defineProperties","value","_toPropertyKey","configurable","writable","arg","_toPrimitive","String","input","hint","prim","toPrimitive","undefined","res","TypeError","Number","DEFAULT_ROW_FAVORITE_LABELS","exports","freeze","addFavorite","removeFavorite","statusFollowed","statusNotFollowed","RowFavoriteToggle","props","resourceKey","rowId","rowLabel","_props$size","size","labels","L","_useIsFavorite","useIsFavorite","isFavorite","toggle","action","ariaLabel","statusLabel","handleChange","_next","e","stopPropagation","handleKeyDown","jsx","title","children","pressed","onChange","onKeyDown","_default"],"sources":["../../../src/lib/v2/patterns/RowFavoriteToggle.tsx"],"sourcesContent":["import * as React from \"react\";\r\n\r\nimport FavoriteToggle from \"../components/FavoriteToggle\";\r\nimport Tooltip from \"../components/Tooltip\";\r\nimport { useIsFavorite } from \"../personalization/capabilities/favorites\";\r\nimport type { RowId } from \"../types/common\";\r\n\r\n/**\r\n * RowFavoriteToggle — Portnet UI v2 (pattern)\r\n *\r\n * A store-connected follow star for ONE row. Reads `useIsFavorite`, renders\r\n * `FavoriteToggle`, and stops its own click/keydown from reaching the row's\r\n * `onRowClick`.\r\n *\r\n * ─────────────────────────────────────────────────────────────────────────────\r\n * WHY THIS BELONGS IN THE LIBRARY (capability gap G-36)\r\n *\r\n * This exact component already existed — as `FavoriteCell`, private inside\r\n * `makeFavoriteColumn`. So the follow star was reachable in ONE context only:\r\n * as a DataGrid column. Every other place a row appears had to rebuild it.\r\n *\r\n * The place that always appears is the MOBILE CARD. `DataGrid` swaps to\r\n * `renderMobileCard` below its `mobileBreakpoint`, and `MobileRowCard` has a\r\n * `leading` slot precisely for a per-row control — but a column definition\r\n * cannot be rendered into a slot, so the host had to re-derive the star by\r\n * hand. Observed in `onssa-export-fe` as a local `MobileFavoriteToggle`, and\r\n * `ms-ti-fe` destructures the identical `MobileRowCard` + `FavoriteToggle` +\r\n * `useIsFavorite` trio for the same reason.\r\n *\r\n * This is the same failure mode G-10 recorded for the card recipe welded\r\n * inside `FormSection`: the library owned the behaviour but exposed it at only\r\n * one composition point, so consumers reimplemented it at the others. And it\r\n * was not a harmless copy — the local twin drifted on the part that matters\r\n * least visibly and most to a screen-reader user. It labelled itself\r\n * \"Ajouter aux favoris\" / \"Retirer des favoris\" while the grid column on the\r\n * SAME page said \"Suivre\" / \"Ne plus suivre\", and it omitted the status\r\n * Tooltip entirely. One list, one control, two accessible names, depending on\r\n * viewport width — exactly what R-2.1 forbids.\r\n *\r\n * `makeFavoriteColumn` now renders this component, so the desktop column and\r\n * the mobile card are guaranteed to agree by construction rather than by\r\n * review.\r\n * ─────────────────────────────────────────────────────────────────────────────\r\n *\r\n * Usage — mobile card `leading` slot:\r\n *\r\n * <MobileRowCard\r\n * leading={\r\n * <RowFavoriteToggle\r\n * resourceKey=\"ti:list\"\r\n * rowId={row.reference}\r\n * rowLabel={row.reference}\r\n * />\r\n * }\r\n * title={row.reference}\r\n * … />\r\n *\r\n * a11y. The accessible name is ACTION-oriented (\"Suivre\" / \"Ne plus suivre\",\r\n * optionally enriched with `rowLabel`) because that is the toggle convention;\r\n * `aria-pressed` — set by `FavoriteToggle` — carries the state. The visible\r\n * status (\"Suivi\" / \"Non suivi\") is shown as a Tooltip on hover/focus. An\r\n * `aria-label` is therefore ALWAYS supplied, which also stops Tooltip from\r\n * mirroring its title onto the trigger and producing a doubled name.\r\n *\r\n * Requires a <UserPersonalizationProvider> ancestor (`useIsFavorite` throws\r\n * otherwise). `rowId` MUST be the same id the grid uses, so the follow and the\r\n * row agree.\r\n */\r\n\r\n/** `FavoriteToggle`'s own size union, re-derived rather than restated. */\r\nexport type FavoriteToggleSize = NonNullable<\r\n React.ComponentProps<typeof FavoriteToggle>[\"size\"]\r\n>;\r\n\r\nexport interface RowFavoriteToggleLabels {\r\n addFavorite: string;\r\n removeFavorite: string;\r\n statusFollowed: string;\r\n statusNotFollowed: string;\r\n}\r\n\r\nexport const DEFAULT_ROW_FAVORITE_LABELS = Object.freeze({\r\n addFavorite: \"Suivre\",\r\n removeFavorite: \"Ne plus suivre\",\r\n statusFollowed: \"Suivi\",\r\n statusNotFollowed: \"Non suivi\",\r\n} satisfies RowFavoriteToggleLabels);\r\n\r\nexport interface RowFavoriteToggleProps {\r\n /** Follow namespace — must match the list's other personalization calls. */\r\n resourceKey: string;\r\n /** Business row id. MUST match the grid's `getRowId` for this row. */\r\n rowId: RowId;\r\n /** Enriches the per-row accessible name (\"Suivre : 2025-IM-0042\"). */\r\n rowLabel?: string | undefined;\r\n /** @default \"sm\" — fits dense rows and card leading slots. */\r\n size?: FavoriteToggleSize | undefined;\r\n labels?: Partial<RowFavoriteToggleLabels> | undefined;\r\n}\r\n\r\nfunction RowFavoriteToggle(props: RowFavoriteToggleProps): React.JSX.Element {\r\n const { resourceKey, rowId, rowLabel, size = \"sm\", labels } = props;\r\n const L: RowFavoriteToggleLabels = labels\r\n ? { ...DEFAULT_ROW_FAVORITE_LABELS, ...labels }\r\n : DEFAULT_ROW_FAVORITE_LABELS;\r\n\r\n const { isFavorite, toggle } = useIsFavorite(resourceKey, rowId);\r\n\r\n const action = isFavorite ? L.removeFavorite : L.addFavorite;\r\n const ariaLabel = rowLabel ? action + \" : \" + rowLabel : action;\r\n const statusLabel = isFavorite ? L.statusFollowed : L.statusNotFollowed;\r\n\r\n const handleChange: NonNullable<\r\n React.ComponentProps<typeof FavoriteToggle>[\"onChange\"]\r\n > = function handleChange(_next, e) {\r\n // Don't let the toggle's click bubble to the row's onRowClick.\r\n if (e && typeof e.stopPropagation === \"function\") e.stopPropagation();\r\n toggle();\r\n };\r\n const handleKeyDown: NonNullable<\r\n React.ComponentProps<typeof FavoriteToggle>[\"onKeyDown\"]\r\n > = function handleKeyDown(e) {\r\n // Prevent row-level Enter/Space (onRowClick) from also firing; the\r\n // button's own native activation is unaffected.\r\n e.stopPropagation();\r\n };\r\n\r\n return (\r\n <Tooltip title={statusLabel}>\r\n <FavoriteToggle\r\n pressed={isFavorite}\r\n onChange={handleChange}\r\n onKeyDown={handleKeyDown}\r\n size={size}\r\n labels={{ addFavorite: L.addFavorite, removeFavorite: L.removeFavorite }}\r\n aria-label={ariaLabel}\r\n />\r\n </Tooltip>\r\n );\r\n}\r\n\r\nexport default RowFavoriteToggle;\r\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* _pickerSerialisation — lecture / ecriture partagees des ponts Formik de date.
|
|
3
|
+
*
|
|
4
|
+
* ── POURQUOI CE MODULE EXISTE ────────────────────────────────────────
|
|
5
|
+
*
|
|
6
|
+
* `FormikDatePicker` portait ces deux fonctions en prive. L'arrivee d'un
|
|
7
|
+
* SECOND pont (`FormikDateTimePicker`, gap G-E) posait le choix : les recopier,
|
|
8
|
+
* ou les partager.
|
|
9
|
+
*
|
|
10
|
+
* Les recopier aurait reproduit exactement la situation que la note S-03 de
|
|
11
|
+
* `FormikDatePicker` raconte. Rappel de ce qu'elle dit : ce pont serialisait
|
|
12
|
+
* VERS moment mais relisait DEPUIS `new Date(raw)`, en ignorant
|
|
13
|
+
* `outputFormat`. L'asymetrie corrompait silencieusement tout format non ISO —
|
|
14
|
+
* `new Date("31-12-2026")` donne Invalid Date, `new Date("05-03-2026")` donne
|
|
15
|
+
* le 3 mai au lieu du 5 mars. Le chemin d'ECRITURE fonctionnait, donc un
|
|
16
|
+
* formulaire rempli puis soumis se comportait correctement : le degat
|
|
17
|
+
* n'apparaissait qu'a la RELECTURE, c'est-a-dire en modification. Un module a
|
|
18
|
+
* livre ce defaut pendant sept lots sous un typecheck strict.
|
|
19
|
+
*
|
|
20
|
+
* Une asymetrie de ce genre entre DEUX ponts serait encore moins visible : ils
|
|
21
|
+
* se ressemblent, personne ne les compare, et chacun a l'air correct
|
|
22
|
+
* isolement. La seule garantie est qu'il n'y ait qu'un exemplaire du couple
|
|
23
|
+
* lecture / ecriture.
|
|
24
|
+
*
|
|
25
|
+
* Module INTERNE : non exporte par la surface publique (prefixe `_`).
|
|
26
|
+
*/
|
|
27
|
+
/**
|
|
28
|
+
* Relit une valeur stockee par Formik vers un `Date`.
|
|
29
|
+
*
|
|
30
|
+
* `outputFormat` est passe pour que la lecture soit SYMETRIQUE de
|
|
31
|
+
* `serialiseDate` : on parse avec le format qui a servi a ecrire, en mode
|
|
32
|
+
* STRICT. Une valeur stockee qui ne correspond pas rend `null` plutot que la
|
|
33
|
+
* meilleure approximation de moment — une date absente est recuperable, une
|
|
34
|
+
* date fausse de deux mois ne l'est pas.
|
|
35
|
+
*/
|
|
36
|
+
export declare const coerceToDate: (raw: unknown, outputFormat?: string) => Date | null;
|
|
37
|
+
/**
|
|
38
|
+
* Serialise un `Date` vers le format demande.
|
|
39
|
+
* undefined -> rend le `Date` tel quel (defaut, compatible)
|
|
40
|
+
* "iso" -> `Date.toISOString()`
|
|
41
|
+
* toute autre chaine -> `moment(date).format(outputFormat)`
|
|
42
|
+
*/
|
|
43
|
+
export declare function serialiseDate(date: Date | null, outputFormat: string | undefined): Date | string | null;
|
|
44
|
+
//# sourceMappingURL=_pickerSerialisation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_pickerSerialisation.d.ts","sourceRoot":"","sources":["../../../src/lib/v2/patterns/_pickerSerialisation.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH;;;;;;;;GAQG;AACH,eAAO,MAAM,YAAY,GACvB,KAAK,OAAO,EACZ,eAAe,MAAM,KACpB,IAAI,GAAG,IAwBT,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,IAAI,GAAG,IAAI,EACjB,YAAY,EAAE,MAAM,GAAG,SAAS,GAC/B,IAAI,GAAG,MAAM,GAAG,IAAI,CAOtB"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.coerceToDate = void 0;
|
|
7
|
+
exports.serialiseDate = serialiseDate;
|
|
8
|
+
var _moment = _interopRequireDefault(require("moment"));
|
|
9
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
|
|
10
|
+
function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); }
|
|
11
|
+
/**
|
|
12
|
+
* _pickerSerialisation — lecture / ecriture partagees des ponts Formik de date.
|
|
13
|
+
*
|
|
14
|
+
* ── POURQUOI CE MODULE EXISTE ────────────────────────────────────────
|
|
15
|
+
*
|
|
16
|
+
* `FormikDatePicker` portait ces deux fonctions en prive. L'arrivee d'un
|
|
17
|
+
* SECOND pont (`FormikDateTimePicker`, gap G-E) posait le choix : les recopier,
|
|
18
|
+
* ou les partager.
|
|
19
|
+
*
|
|
20
|
+
* Les recopier aurait reproduit exactement la situation que la note S-03 de
|
|
21
|
+
* `FormikDatePicker` raconte. Rappel de ce qu'elle dit : ce pont serialisait
|
|
22
|
+
* VERS moment mais relisait DEPUIS `new Date(raw)`, en ignorant
|
|
23
|
+
* `outputFormat`. L'asymetrie corrompait silencieusement tout format non ISO —
|
|
24
|
+
* `new Date("31-12-2026")` donne Invalid Date, `new Date("05-03-2026")` donne
|
|
25
|
+
* le 3 mai au lieu du 5 mars. Le chemin d'ECRITURE fonctionnait, donc un
|
|
26
|
+
* formulaire rempli puis soumis se comportait correctement : le degat
|
|
27
|
+
* n'apparaissait qu'a la RELECTURE, c'est-a-dire en modification. Un module a
|
|
28
|
+
* livre ce defaut pendant sept lots sous un typecheck strict.
|
|
29
|
+
*
|
|
30
|
+
* Une asymetrie de ce genre entre DEUX ponts serait encore moins visible : ils
|
|
31
|
+
* se ressemblent, personne ne les compare, et chacun a l'air correct
|
|
32
|
+
* isolement. La seule garantie est qu'il n'y ait qu'un exemplaire du couple
|
|
33
|
+
* lecture / ecriture.
|
|
34
|
+
*
|
|
35
|
+
* Module INTERNE : non exporte par la surface publique (prefixe `_`).
|
|
36
|
+
*/
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Relit une valeur stockee par Formik vers un `Date`.
|
|
40
|
+
*
|
|
41
|
+
* `outputFormat` est passe pour que la lecture soit SYMETRIQUE de
|
|
42
|
+
* `serialiseDate` : on parse avec le format qui a servi a ecrire, en mode
|
|
43
|
+
* STRICT. Une valeur stockee qui ne correspond pas rend `null` plutot que la
|
|
44
|
+
* meilleure approximation de moment — une date absente est recuperable, une
|
|
45
|
+
* date fausse de deux mois ne l'est pas.
|
|
46
|
+
*/
|
|
47
|
+
var coerceToDate = exports.coerceToDate = function coerceToDate(raw, outputFormat) {
|
|
48
|
+
if (raw == null || raw === "") return null;
|
|
49
|
+
if (raw instanceof Date) return raw;
|
|
50
|
+
if (_typeof(raw) === "object" && typeof raw.toDate === "function") {
|
|
51
|
+
var _d$getTime;
|
|
52
|
+
var _d = raw.toDate();
|
|
53
|
+
return isNaN(_d === null || _d === void 0 ? void 0 : (_d$getTime = _d.getTime) === null || _d$getTime === void 0 ? void 0 : _d$getTime.call(_d)) ? null : _d;
|
|
54
|
+
}
|
|
55
|
+
/* Garde sur `typeof raw === "string"` : un horodatage numerique garde le
|
|
56
|
+
* chemin `new Date(number)`, `moment(number, format)` n'ayant pas de sens.
|
|
57
|
+
* "iso" est exclu : ce n'est pas un jeton moment, et `new Date(isoString)`
|
|
58
|
+
* est deja correct. */
|
|
59
|
+
if (typeof raw === "string" && outputFormat !== undefined && outputFormat !== "iso") {
|
|
60
|
+
var parsed = (0, _moment["default"])(raw, outputFormat, true);
|
|
61
|
+
return parsed.isValid() ? parsed.toDate() : null;
|
|
62
|
+
}
|
|
63
|
+
var d = new Date(raw);
|
|
64
|
+
return isNaN(d.getTime()) ? null : d;
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Serialise un `Date` vers le format demande.
|
|
69
|
+
* undefined -> rend le `Date` tel quel (defaut, compatible)
|
|
70
|
+
* "iso" -> `Date.toISOString()`
|
|
71
|
+
* toute autre chaine -> `moment(date).format(outputFormat)`
|
|
72
|
+
*/
|
|
73
|
+
function serialiseDate(date, outputFormat) {
|
|
74
|
+
if (!date || !(date instanceof Date) || isNaN(date.getTime())) {
|
|
75
|
+
return outputFormat ? "" : null;
|
|
76
|
+
}
|
|
77
|
+
if (!outputFormat) return date;
|
|
78
|
+
if (outputFormat === "iso") return date.toISOString();
|
|
79
|
+
return (0, _moment["default"])(date).format(outputFormat);
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=_pickerSerialisation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_pickerSerialisation.js","names":["_moment","_interopRequireDefault","require","obj","__esModule","_typeof","Symbol","iterator","constructor","prototype","coerceToDate","exports","raw","outputFormat","Date","toDate","_d$getTime","d","isNaN","getTime","call","undefined","parsed","moment","isValid","serialiseDate","date","toISOString","format"],"sources":["../../../src/lib/v2/patterns/_pickerSerialisation.ts"],"sourcesContent":["import moment from \"moment\";\r\n\r\n/**\r\n * _pickerSerialisation — lecture / ecriture partagees des ponts Formik de date.\r\n *\r\n * ── POURQUOI CE MODULE EXISTE ────────────────────────────────────────\r\n *\r\n * `FormikDatePicker` portait ces deux fonctions en prive. L'arrivee d'un\r\n * SECOND pont (`FormikDateTimePicker`, gap G-E) posait le choix : les recopier,\r\n * ou les partager.\r\n *\r\n * Les recopier aurait reproduit exactement la situation que la note S-03 de\r\n * `FormikDatePicker` raconte. Rappel de ce qu'elle dit : ce pont serialisait\r\n * VERS moment mais relisait DEPUIS `new Date(raw)`, en ignorant\r\n * `outputFormat`. L'asymetrie corrompait silencieusement tout format non ISO —\r\n * `new Date(\"31-12-2026\")` donne Invalid Date, `new Date(\"05-03-2026\")` donne\r\n * le 3 mai au lieu du 5 mars. Le chemin d'ECRITURE fonctionnait, donc un\r\n * formulaire rempli puis soumis se comportait correctement : le degat\r\n * n'apparaissait qu'a la RELECTURE, c'est-a-dire en modification. Un module a\r\n * livre ce defaut pendant sept lots sous un typecheck strict.\r\n *\r\n * Une asymetrie de ce genre entre DEUX ponts serait encore moins visible : ils\r\n * se ressemblent, personne ne les compare, et chacun a l'air correct\r\n * isolement. La seule garantie est qu'il n'y ait qu'un exemplaire du couple\r\n * lecture / ecriture.\r\n *\r\n * Module INTERNE : non exporte par la surface publique (prefixe `_`).\r\n */\r\n\r\n/**\r\n * Relit une valeur stockee par Formik vers un `Date`.\r\n *\r\n * `outputFormat` est passe pour que la lecture soit SYMETRIQUE de\r\n * `serialiseDate` : on parse avec le format qui a servi a ecrire, en mode\r\n * STRICT. Une valeur stockee qui ne correspond pas rend `null` plutot que la\r\n * meilleure approximation de moment — une date absente est recuperable, une\r\n * date fausse de deux mois ne l'est pas.\r\n */\r\nexport const coerceToDate = (\r\n raw: unknown,\r\n outputFormat?: string\r\n): Date | null => {\r\n if (raw == null || raw === \"\") return null;\r\n if (raw instanceof Date) return raw;\r\n if (\r\n typeof raw === \"object\" &&\r\n typeof (raw as { toDate?: () => Date }).toDate === \"function\"\r\n ) {\r\n const d = (raw as { toDate: () => Date }).toDate();\r\n return isNaN(d?.getTime?.()) ? null : d;\r\n }\r\n /* Garde sur `typeof raw === \"string\"` : un horodatage numerique garde le\r\n * chemin `new Date(number)`, `moment(number, format)` n'ayant pas de sens.\r\n * \"iso\" est exclu : ce n'est pas un jeton moment, et `new Date(isoString)`\r\n * est deja correct. */\r\n if (\r\n typeof raw === \"string\" &&\r\n outputFormat !== undefined &&\r\n outputFormat !== \"iso\"\r\n ) {\r\n const parsed = moment(raw, outputFormat, true);\r\n return parsed.isValid() ? parsed.toDate() : null;\r\n }\r\n const d = new Date(raw as string | number);\r\n return isNaN(d.getTime()) ? null : d;\r\n};\r\n\r\n/**\r\n * Serialise un `Date` vers le format demande.\r\n * undefined -> rend le `Date` tel quel (defaut, compatible)\r\n * \"iso\" -> `Date.toISOString()`\r\n * toute autre chaine -> `moment(date).format(outputFormat)`\r\n */\r\nexport function serialiseDate(\r\n date: Date | null,\r\n outputFormat: string | undefined\r\n): Date | string | null {\r\n if (!date || !(date instanceof Date) || isNaN(date.getTime())) {\r\n return outputFormat ? \"\" : null;\r\n }\r\n if (!outputFormat) return date;\r\n if (outputFormat === \"iso\") return date.toISOString();\r\n return moment(date).format(outputFormat);\r\n}\r\n"],"mappings":";;;;;;;AAAA,IAAAA,OAAA,GAAAC,sBAAA,CAAAC,OAAA;AAA4B,SAAAD,uBAAAE,GAAA,WAAAA,GAAA,IAAAA,GAAA,CAAAC,UAAA,GAAAD,GAAA,gBAAAA,GAAA;AAAA,SAAAE,QAAAF,GAAA,sCAAAE,OAAA,wBAAAC,MAAA,uBAAAA,MAAA,CAAAC,QAAA,aAAAJ,GAAA,kBAAAA,GAAA,gBAAAA,GAAA,WAAAA,GAAA,yBAAAG,MAAA,IAAAH,GAAA,CAAAK,WAAA,KAAAF,MAAA,IAAAH,GAAA,KAAAG,MAAA,CAAAG,SAAA,qBAAAN,GAAA,KAAAE,OAAA,CAAAF,GAAA;AAE5B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,IAAMO,YAAY,GAAAC,OAAA,CAAAD,YAAA,GAAG,SAAfA,YAAYA,CACvBE,GAAY,EACZC,YAAqB,EACL;EAChB,IAAID,GAAG,IAAI,IAAI,IAAIA,GAAG,KAAK,EAAE,EAAE,OAAO,IAAI;EAC1C,IAAIA,GAAG,YAAYE,IAAI,EAAE,OAAOF,GAAG;EACnC,IACEP,OAAA,CAAOO,GAAG,MAAK,QAAQ,IACvB,OAAQA,GAAG,CAA6BG,MAAM,KAAK,UAAU,EAC7D;IAAA,IAAAC,UAAA;IACA,IAAMC,EAAC,GAAIL,GAAG,CAA4BG,MAAM,CAAC,CAAC;IAClD,OAAOG,KAAK,CAACD,EAAC,aAADA,EAAC,wBAAAD,UAAA,GAADC,EAAC,CAAEE,OAAO,cAAAH,UAAA,uBAAVA,UAAA,CAAAI,IAAA,CAAAH,EAAa,CAAC,CAAC,GAAG,IAAI,GAAGA,EAAC;EACzC;EACA;AACF;AACA;AACA;EACE,IACE,OAAOL,GAAG,KAAK,QAAQ,IACvBC,YAAY,KAAKQ,SAAS,IAC1BR,YAAY,KAAK,KAAK,EACtB;IACA,IAAMS,MAAM,GAAG,IAAAC,kBAAM,EAACX,GAAG,EAAEC,YAAY,EAAE,IAAI,CAAC;IAC9C,OAAOS,MAAM,CAACE,OAAO,CAAC,CAAC,GAAGF,MAAM,CAACP,MAAM,CAAC,CAAC,GAAG,IAAI;EAClD;EACA,IAAME,CAAC,GAAG,IAAIH,IAAI,CAACF,GAAsB,CAAC;EAC1C,OAAOM,KAAK,CAACD,CAAC,CAACE,OAAO,CAAC,CAAC,CAAC,GAAG,IAAI,GAAGF,CAAC;AACtC,CAAC;;AAED;AACA;AACA;AACA;AACA;AACA;AACO,SAASQ,aAAaA,CAC3BC,IAAiB,EACjBb,YAAgC,EACV;EACtB,IAAI,CAACa,IAAI,IAAI,EAAEA,IAAI,YAAYZ,IAAI,CAAC,IAAII,KAAK,CAACQ,IAAI,CAACP,OAAO,CAAC,CAAC,CAAC,EAAE;IAC7D,OAAON,YAAY,GAAG,EAAE,GAAG,IAAI;EACjC;EACA,IAAI,CAACA,YAAY,EAAE,OAAOa,IAAI;EAC9B,IAAIb,YAAY,KAAK,KAAK,EAAE,OAAOa,IAAI,CAACC,WAAW,CAAC,CAAC;EACrD,OAAO,IAAAJ,kBAAM,EAACG,IAAI,CAAC,CAACE,MAAM,CAACf,YAAY,CAAC;AAC1C","ignoreList":[]}
|