@adea-ai/ui 0.95.4 → 0.95.6
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/components/composites/settings/settings-navigation.d.ts +3 -16
- package/dist/components/composites/settings/settings-navigation.d.ts.map +1 -1
- package/dist/components/composites/settings/settings-navigation.js +24 -4
- package/dist/components/composites/settings/settings-navigation.js.map +1 -1
- package/dist/r/src/components/composites/settings/settings-navigation.tsx +35 -4
- package/package.json +1 -1
- package/src/components/composites/settings/settings-navigation.tsx +35 -4
|
@@ -19,23 +19,10 @@ export type SettingsNavigationProps = Omit<TabsListProps, 'appearance' | 'childr
|
|
|
19
19
|
value: string;
|
|
20
20
|
/** Called when the already-selected destination is activated again. */
|
|
21
21
|
onReselect?: (value: string) => void;
|
|
22
|
-
/** Reveal the selected row on value changes and window resizes. Defaults to nearest
|
|
23
|
-
|
|
24
|
-
/** Every tab list needs a label independent of its visible group headings. */
|
|
22
|
+
/** Reveal the selected row on value changes and window resizes. Defaults to nearest scrolling
|
|
23
|
+
* of the ancestors that expose a scroll affordance; hidden-overflow ancestors never move. */
|
|
24
|
+
revealSelected?: boolean | ((trigger: HTMLButtonElement | undefined) => void); /** Every tab list needs a label independent of its visible group headings. */
|
|
25
25
|
'aria-label': string;
|
|
26
26
|
};
|
|
27
|
-
/**
|
|
28
|
-
* SettingsNavigation.
|
|
29
|
-
*
|
|
30
|
-
* A grouped vertical tab list for sibling settings panels. It composes the
|
|
31
|
-
* shared Tabs behaviour with the shared sidebar row recipe; the host supplies
|
|
32
|
-
* the controlled value, panel content, icons and any persistence or routing.
|
|
33
|
-
* Use ordinary tabs for a short, ungrouped row of view choices.
|
|
34
|
-
*
|
|
35
|
-
* Kobalte owns roving focus, arrow keys, selection and tab/panel ARIA. This
|
|
36
|
-
* component adds no URL, storage or host-specific state. Set
|
|
37
|
-
* `revealSelected={false}` when the surrounding layout does not use an internal
|
|
38
|
-
* scrolling viewport.
|
|
39
|
-
*/
|
|
40
27
|
export declare function SettingsNavigation(props: SettingsNavigationProps): JSX.Element;
|
|
41
28
|
//# sourceMappingURL=settings-navigation.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"settings-navigation.d.ts","sourceRoot":"","sources":["../../../../src/components/composites/settings/settings-navigation.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,UAAU,CAAA;AAInC,OAAO,EAAyB,KAAK,aAAa,EAAE,MAAM,eAAe,CAAA;AAEzE,gFAAgF;AAChF,MAAM,MAAM,sBAAsB,GAAG;IACnC,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,GAAG,CAAC,OAAO,CAAA;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB,CAAA;AAED,kEAAkE;AAClE,MAAM,MAAM,uBAAuB,GAAG;IACpC,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,SAAS,sBAAsB,EAAE,CAAA;CACzC,CAAA;AAED,MAAM,MAAM,uBAAuB,GAAG,IAAI,CACxC,aAAa,EACb,YAAY,GAAG,UAAU,GAAG,aAAa,CAC1C,GAAG;IACF,6EAA6E;IAC7E,MAAM,EAAE,SAAS,uBAAuB,EAAE,CAAA;IAC1C,kEAAkE;IAClE,KAAK,EAAE,MAAM,CAAA;IACb,uEAAuE;IACvE,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IACpC
|
|
1
|
+
{"version":3,"file":"settings-navigation.d.ts","sourceRoot":"","sources":["../../../../src/components/composites/settings/settings-navigation.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,UAAU,CAAA;AAInC,OAAO,EAAyB,KAAK,aAAa,EAAE,MAAM,eAAe,CAAA;AAEzE,gFAAgF;AAChF,MAAM,MAAM,sBAAsB,GAAG;IACnC,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,GAAG,CAAC,OAAO,CAAA;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB,CAAA;AAED,kEAAkE;AAClE,MAAM,MAAM,uBAAuB,GAAG;IACpC,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,SAAS,sBAAsB,EAAE,CAAA;CACzC,CAAA;AAED,MAAM,MAAM,uBAAuB,GAAG,IAAI,CACxC,aAAa,EACb,YAAY,GAAG,UAAU,GAAG,aAAa,CAC1C,GAAG;IACF,6EAA6E;IAC7E,MAAM,EAAE,SAAS,uBAAuB,EAAE,CAAA;IAC1C,kEAAkE;IAClE,KAAK,EAAE,MAAM,CAAA;IACb,uEAAuE;IACvE,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IACpC;iGAC6F;IAC7F,cAAc,CAAC,EACX,OAAO,GACP,CAAC,CACC,OAAO,EAAE,iBAAiB,GAAG,SAAS,KACnC,IAAI,CAAC,CAAA,CAAC,8EAA8E;IAC7F,YAAY,EAAE,MAAM,CAAA;CACrB,CAAA;AA0CD,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,uBAAuB,eAqFhE"}
|
|
@@ -19,6 +19,29 @@ var _tmpl$2 = /*#__PURE__*/ template(`<span class="min-w-0 truncate">`);
|
|
|
19
19
|
* `revealSelected={false}` when the surrounding layout does not use an internal
|
|
20
20
|
* scrolling viewport.
|
|
21
21
|
*/
|
|
22
|
+
/**
|
|
23
|
+
* Reveal by scrolling only the ancestors that expose a scroll affordance
|
|
24
|
+
* (`auto` or `scroll`), by the exact nearest-edge delta. `scrollIntoView` also
|
|
25
|
+
* pans `overflow: hidden` ancestors, which are programmatically scrollable but
|
|
26
|
+
* give the user no way back, so one over-pan left earlier rows permanently
|
|
27
|
+
* clipped outside the viewport with no scroll to recover them (#182).
|
|
28
|
+
*/
|
|
29
|
+
function scrollContainerNearest(container, row) {
|
|
30
|
+
const style = window.getComputedStyle(container);
|
|
31
|
+
const box = container.getBoundingClientRect();
|
|
32
|
+
const rowBox = row.getBoundingClientRect();
|
|
33
|
+
if (style.overflowX === "auto" || style.overflowX === "scroll") {
|
|
34
|
+
if (rowBox.left < box.left) container.scrollLeft += rowBox.left - box.left;
|
|
35
|
+
else if (rowBox.right > box.right) container.scrollLeft += rowBox.right - box.right;
|
|
36
|
+
}
|
|
37
|
+
if (style.overflowY === "auto" || style.overflowY === "scroll") {
|
|
38
|
+
if (rowBox.top < box.top) container.scrollTop += rowBox.top - box.top;
|
|
39
|
+
else if (rowBox.bottom > box.bottom) container.scrollTop += rowBox.bottom - box.bottom;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
function revealNearest(row) {
|
|
43
|
+
for (let container = row.parentElement; container; container = container.parentElement) scrollContainerNearest(container, row);
|
|
44
|
+
}
|
|
22
45
|
function SettingsNavigation(props) {
|
|
23
46
|
const [local, rest] = splitProps(props, [
|
|
24
47
|
"class",
|
|
@@ -37,10 +60,7 @@ function SettingsNavigation(props) {
|
|
|
37
60
|
const revealCurrent = () => {
|
|
38
61
|
const trigger = triggers.get(value);
|
|
39
62
|
if (typeof reveal === "function") reveal(trigger);
|
|
40
|
-
else trigger
|
|
41
|
-
block: "nearest",
|
|
42
|
-
inline: "nearest"
|
|
43
|
-
});
|
|
63
|
+
else if (trigger) revealNearest(trigger);
|
|
44
64
|
};
|
|
45
65
|
revealCurrent();
|
|
46
66
|
window.addEventListener("resize", revealCurrent);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"settings-navigation.js","names":["JSX","createEffect","createUniqueId","onCleanup","splitProps","cn","sidebarNavItemClass","sidebarNavItemStateClass","TabsList","TabsTrigger","TabsListProps","SettingsNavigationItem","value","label","icon","Element","disabled","SettingsNavigationGroup","items","SettingsNavigationProps","Omit","groups","onReselect","revealSelected","trigger","HTMLButtonElement","
|
|
1
|
+
{"version":3,"file":"settings-navigation.js","names":["JSX","createEffect","createUniqueId","onCleanup","splitProps","cn","sidebarNavItemClass","sidebarNavItemStateClass","TabsList","TabsTrigger","TabsListProps","SettingsNavigationItem","value","label","icon","Element","disabled","SettingsNavigationGroup","items","SettingsNavigationProps","Omit","groups","onReselect","revealSelected","trigger","HTMLButtonElement","scrollContainerNearest","container","HTMLElement","row","style","window","getComputedStyle","box","getBoundingClientRect","rowBox","overflowX","left","scrollLeft","right","overflowY","top","scrollTop","bottom","revealNearest","parentElement","SettingsNavigation","props","local","rest","triggers","Map","groupIdPrefix","reveal","revealCurrent","get","addEventListener","removeEventListener","_$createComponent","_$mergeProps","aria-label","orientation","class","children","map","group","groupIndex","groupId","_el$","_tmpl$","_el$2","firstChild","_el$3","nextSibling","_$setAttribute","_$insert","item","ref","element","set","delete","onClick","idle","_$memo","_el$4","_tmpl$2","_$createComponent","_$mergeProps","_$memo"],"sources":["../../../../src/components/composites/settings/settings-navigation.tsx"],"sourcesContent":["import type { JSX } from 'solid-js'\nimport { createEffect, createUniqueId, onCleanup, splitProps } from 'solid-js'\nimport { cn } from '#lib/utils'\nimport { sidebarNavItemClass, sidebarNavItemStateClass } from '../../layout/sidebar-nav/sidebar-nav'\nimport { TabsList, TabsTrigger, type TabsListProps } from '../../ui/tabs'\n\n/** One host-owned destination in a settings tab list. Values must be unique. */\nexport type SettingsNavigationItem = {\n value: string\n label: string\n icon?: JSX.Element\n disabled?: boolean\n}\n\n/** A visible, accessibly named group of settings destinations. */\nexport type SettingsNavigationGroup = {\n label: string\n items: readonly SettingsNavigationItem[]\n}\n\nexport type SettingsNavigationProps = Omit<\n TabsListProps,\n 'appearance' | 'children' | 'orientation'\n> & {\n /** Groups are presentation only; the host owns the tab values and panels. */\n groups: readonly SettingsNavigationGroup[]\n /** The same controlled value supplied to the enclosing `Tabs`. */\n value: string\n /** Called when the already-selected destination is activated again. */\n onReselect?: (value: string) => void\n /** Reveal the selected row on value changes and window resizes. Defaults to nearest scrolling\n * of the ancestors that expose a scroll affordance; hidden-overflow ancestors never move. */\n revealSelected?:\n | boolean\n | ((\n trigger: HTMLButtonElement | undefined\n ) => void) /** Every tab list needs a label independent of its visible group headings. */\n 'aria-label': string\n}\n\n/**\n * SettingsNavigation.\n *\n * A grouped vertical tab list for sibling settings panels. It composes the\n * shared Tabs behaviour with the shared sidebar row recipe; the host supplies\n * the controlled value, panel content, icons and any persistence or routing.\n * Use ordinary tabs for a short, ungrouped row of view choices.\n *\n * Kobalte owns roving focus, arrow keys, selection and tab/panel ARIA. This\n * component adds no URL, storage or host-specific state. Set\n * `revealSelected={false}` when the surrounding layout does not use an internal\n * scrolling viewport.\n */\n/**\n * Reveal by scrolling only the ancestors that expose a scroll affordance\n * (`auto` or `scroll`), by the exact nearest-edge delta. `scrollIntoView` also\n * pans `overflow: hidden` ancestors, which are programmatically scrollable but\n * give the user no way back, so one over-pan left earlier rows permanently\n * clipped outside the viewport with no scroll to recover them (#182).\n */\nfunction scrollContainerNearest(container: HTMLElement, row: HTMLElement): void {\n const style = window.getComputedStyle(container)\n const box = container.getBoundingClientRect()\n const rowBox = row.getBoundingClientRect()\n if (style.overflowX === 'auto' || style.overflowX === 'scroll') {\n if (rowBox.left < box.left) container.scrollLeft += rowBox.left - box.left\n else if (rowBox.right > box.right) container.scrollLeft += rowBox.right - box.right\n }\n if (style.overflowY === 'auto' || style.overflowY === 'scroll') {\n if (rowBox.top < box.top) container.scrollTop += rowBox.top - box.top\n else if (rowBox.bottom > box.bottom) container.scrollTop += rowBox.bottom - box.bottom\n }\n}\n\nfunction revealNearest(row: HTMLElement): void {\n for (let container = row.parentElement; container; container = container.parentElement) {\n scrollContainerNearest(container, row)\n }\n}\n\nexport function SettingsNavigation(props: SettingsNavigationProps) {\n const [local, rest] = splitProps(props, [\n 'class',\n 'aria-label',\n 'groups',\n 'value',\n 'onReselect',\n 'revealSelected',\n ])\n const triggers = new Map<string, HTMLButtonElement>()\n const groupIdPrefix = `settings-navigation-${createUniqueId()}`\n\n createEffect(() => {\n const value = local.value\n const reveal = local.revealSelected\n if (reveal === false) return\n\n const revealCurrent = () => {\n const trigger = triggers.get(value)\n if (typeof reveal === 'function') reveal(trigger)\n else if (trigger) revealNearest(trigger)\n }\n\n revealCurrent()\n window.addEventListener('resize', revealCurrent)\n onCleanup(() => window.removeEventListener('resize', revealCurrent))\n })\n\n return (\n <TabsList\n data-slot=\"settings-navigation\"\n aria-label={local['aria-label']}\n orientation=\"vertical\"\n class={cn(\n 'flex max-h-full min-h-0 min-w-0 shrink-0 flex-col items-stretch justify-start gap-2 overflow-x-hidden overflow-y-auto px-2 py-2',\n local.class\n )}\n {...rest}\n >\n {local.groups.map((group, groupIndex) => {\n const groupId = `${groupIdPrefix}-group-${groupIndex}`\n return (\n <div\n role=\"none\"\n data-slot=\"settings-navigation-group\"\n class=\"flex min-w-0 flex-col gap-0.5\"\n >\n <span id={groupId} class=\"sr-only\">\n {group.label}\n </span>\n <span\n aria-hidden=\"true\"\n class=\"px-2 py-1.5 text-2xs font-medium tracking-wide text-sidebar-muted-foreground uppercase\"\n >\n {group.label}\n </span>\n {group.items.map((item) => (\n <TabsTrigger\n data-slot=\"settings-navigation-trigger\"\n orientation=\"vertical\"\n aria-describedby={groupId}\n value={item.value}\n disabled={item.disabled}\n ref={(element: HTMLButtonElement | undefined) => {\n if (element) triggers.set(item.value, element)\n else triggers.delete(item.value)\n }}\n onClick={() => {\n if (local.value === item.value) local.onReselect?.(item.value)\n }}\n class={cn(\n sidebarNavItemClass,\n sidebarNavItemStateClass.idle,\n 'h-row-lg w-full justify-start border-0 px-3 py-2 text-left data-[selected]:bg-primary-subtle data-[selected]:text-foreground'\n )}\n >\n {item.icon}\n <span class=\"min-w-0 truncate\">{item.label}</span>\n </TabsTrigger>\n ))}\n </div>\n )\n })}\n </TabsList>\n )\n}\n"],"mappings":"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"}
|
|
@@ -28,9 +28,13 @@ export type SettingsNavigationProps = Omit<
|
|
|
28
28
|
value: string
|
|
29
29
|
/** Called when the already-selected destination is activated again. */
|
|
30
30
|
onReselect?: (value: string) => void
|
|
31
|
-
/** Reveal the selected row on value changes and window resizes. Defaults to nearest
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
/** Reveal the selected row on value changes and window resizes. Defaults to nearest scrolling
|
|
32
|
+
* of the ancestors that expose a scroll affordance; hidden-overflow ancestors never move. */
|
|
33
|
+
revealSelected?:
|
|
34
|
+
| boolean
|
|
35
|
+
| ((
|
|
36
|
+
trigger: HTMLButtonElement | undefined
|
|
37
|
+
) => void) /** Every tab list needs a label independent of its visible group headings. */
|
|
34
38
|
'aria-label': string
|
|
35
39
|
}
|
|
36
40
|
|
|
@@ -47,6 +51,33 @@ export type SettingsNavigationProps = Omit<
|
|
|
47
51
|
* `revealSelected={false}` when the surrounding layout does not use an internal
|
|
48
52
|
* scrolling viewport.
|
|
49
53
|
*/
|
|
54
|
+
/**
|
|
55
|
+
* Reveal by scrolling only the ancestors that expose a scroll affordance
|
|
56
|
+
* (`auto` or `scroll`), by the exact nearest-edge delta. `scrollIntoView` also
|
|
57
|
+
* pans `overflow: hidden` ancestors, which are programmatically scrollable but
|
|
58
|
+
* give the user no way back, so one over-pan left earlier rows permanently
|
|
59
|
+
* clipped outside the viewport with no scroll to recover them (#182).
|
|
60
|
+
*/
|
|
61
|
+
function scrollContainerNearest(container: HTMLElement, row: HTMLElement): void {
|
|
62
|
+
const style = window.getComputedStyle(container)
|
|
63
|
+
const box = container.getBoundingClientRect()
|
|
64
|
+
const rowBox = row.getBoundingClientRect()
|
|
65
|
+
if (style.overflowX === 'auto' || style.overflowX === 'scroll') {
|
|
66
|
+
if (rowBox.left < box.left) container.scrollLeft += rowBox.left - box.left
|
|
67
|
+
else if (rowBox.right > box.right) container.scrollLeft += rowBox.right - box.right
|
|
68
|
+
}
|
|
69
|
+
if (style.overflowY === 'auto' || style.overflowY === 'scroll') {
|
|
70
|
+
if (rowBox.top < box.top) container.scrollTop += rowBox.top - box.top
|
|
71
|
+
else if (rowBox.bottom > box.bottom) container.scrollTop += rowBox.bottom - box.bottom
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function revealNearest(row: HTMLElement): void {
|
|
76
|
+
for (let container = row.parentElement; container; container = container.parentElement) {
|
|
77
|
+
scrollContainerNearest(container, row)
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
50
81
|
export function SettingsNavigation(props: SettingsNavigationProps) {
|
|
51
82
|
const [local, rest] = splitProps(props, [
|
|
52
83
|
'class',
|
|
@@ -67,7 +98,7 @@ export function SettingsNavigation(props: SettingsNavigationProps) {
|
|
|
67
98
|
const revealCurrent = () => {
|
|
68
99
|
const trigger = triggers.get(value)
|
|
69
100
|
if (typeof reveal === 'function') reveal(trigger)
|
|
70
|
-
else trigger
|
|
101
|
+
else if (trigger) revealNearest(trigger)
|
|
71
102
|
}
|
|
72
103
|
|
|
73
104
|
revealCurrent()
|
package/package.json
CHANGED
|
@@ -28,9 +28,13 @@ export type SettingsNavigationProps = Omit<
|
|
|
28
28
|
value: string
|
|
29
29
|
/** Called when the already-selected destination is activated again. */
|
|
30
30
|
onReselect?: (value: string) => void
|
|
31
|
-
/** Reveal the selected row on value changes and window resizes. Defaults to nearest
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
/** Reveal the selected row on value changes and window resizes. Defaults to nearest scrolling
|
|
32
|
+
* of the ancestors that expose a scroll affordance; hidden-overflow ancestors never move. */
|
|
33
|
+
revealSelected?:
|
|
34
|
+
| boolean
|
|
35
|
+
| ((
|
|
36
|
+
trigger: HTMLButtonElement | undefined
|
|
37
|
+
) => void) /** Every tab list needs a label independent of its visible group headings. */
|
|
34
38
|
'aria-label': string
|
|
35
39
|
}
|
|
36
40
|
|
|
@@ -47,6 +51,33 @@ export type SettingsNavigationProps = Omit<
|
|
|
47
51
|
* `revealSelected={false}` when the surrounding layout does not use an internal
|
|
48
52
|
* scrolling viewport.
|
|
49
53
|
*/
|
|
54
|
+
/**
|
|
55
|
+
* Reveal by scrolling only the ancestors that expose a scroll affordance
|
|
56
|
+
* (`auto` or `scroll`), by the exact nearest-edge delta. `scrollIntoView` also
|
|
57
|
+
* pans `overflow: hidden` ancestors, which are programmatically scrollable but
|
|
58
|
+
* give the user no way back, so one over-pan left earlier rows permanently
|
|
59
|
+
* clipped outside the viewport with no scroll to recover them (#182).
|
|
60
|
+
*/
|
|
61
|
+
function scrollContainerNearest(container: HTMLElement, row: HTMLElement): void {
|
|
62
|
+
const style = window.getComputedStyle(container)
|
|
63
|
+
const box = container.getBoundingClientRect()
|
|
64
|
+
const rowBox = row.getBoundingClientRect()
|
|
65
|
+
if (style.overflowX === 'auto' || style.overflowX === 'scroll') {
|
|
66
|
+
if (rowBox.left < box.left) container.scrollLeft += rowBox.left - box.left
|
|
67
|
+
else if (rowBox.right > box.right) container.scrollLeft += rowBox.right - box.right
|
|
68
|
+
}
|
|
69
|
+
if (style.overflowY === 'auto' || style.overflowY === 'scroll') {
|
|
70
|
+
if (rowBox.top < box.top) container.scrollTop += rowBox.top - box.top
|
|
71
|
+
else if (rowBox.bottom > box.bottom) container.scrollTop += rowBox.bottom - box.bottom
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function revealNearest(row: HTMLElement): void {
|
|
76
|
+
for (let container = row.parentElement; container; container = container.parentElement) {
|
|
77
|
+
scrollContainerNearest(container, row)
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
50
81
|
export function SettingsNavigation(props: SettingsNavigationProps) {
|
|
51
82
|
const [local, rest] = splitProps(props, [
|
|
52
83
|
'class',
|
|
@@ -67,7 +98,7 @@ export function SettingsNavigation(props: SettingsNavigationProps) {
|
|
|
67
98
|
const revealCurrent = () => {
|
|
68
99
|
const trigger = triggers.get(value)
|
|
69
100
|
if (typeof reveal === 'function') reveal(trigger)
|
|
70
|
-
else trigger
|
|
101
|
+
else if (trigger) revealNearest(trigger)
|
|
71
102
|
}
|
|
72
103
|
|
|
73
104
|
revealCurrent()
|