@tastic/profile 0.14.1 → 0.15.0
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/index.d.mts +59 -27
- package/dist/index.d.ts +59 -27
- package/dist/index.js +315 -227
- package/dist/index.mjs +272 -187
- package/package.json +8 -8
- package/src/OptionPicker.tsx +64 -0
- package/src/PickerMenu.tsx +481 -0
- package/src/ProfilePicker.tsx +54 -425
- package/src/ProfilesManager.tsx +7 -5
- package/src/index.ts +2 -1
- package/src/redux/seatColorsSlice.ts +79 -29
package/dist/index.mjs
CHANGED
|
@@ -5,6 +5,14 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
|
|
|
5
5
|
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
6
6
|
});
|
|
7
7
|
|
|
8
|
+
// src/PickerMenu.tsx
|
|
9
|
+
import { defaultColors, FadingScrollView, getContrastColor as getContrastColor2 } from "@rific/auto-paper";
|
|
10
|
+
import { TouchableRipple } from "@rific/feedback-press";
|
|
11
|
+
import { PopoverBody, useAutoAlign } from "@tastic/hud";
|
|
12
|
+
import { useState } from "react";
|
|
13
|
+
import { StyleSheet as StyleSheet2, View as View2 } from "react-native";
|
|
14
|
+
import { Icon as Icon2, Text as Text2 } from "react-native-paper";
|
|
15
|
+
|
|
8
16
|
// src/IdentityChip.tsx
|
|
9
17
|
import { getContrastColor } from "@rific/auto-paper";
|
|
10
18
|
import { StyleSheet, View } from "react-native";
|
|
@@ -27,36 +35,8 @@ var styles = StyleSheet.create({
|
|
|
27
35
|
}
|
|
28
36
|
});
|
|
29
37
|
|
|
30
|
-
// src/
|
|
31
|
-
import {
|
|
32
|
-
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
33
|
-
var ProfileColorContext = createContext(void 0);
|
|
34
|
-
function ProfileColorProvider({ preview, children }) {
|
|
35
|
-
return /* @__PURE__ */ jsx2(ProfileColorContext.Provider, { value: preview, children });
|
|
36
|
-
}
|
|
37
|
-
function useProfileColorPreview() {
|
|
38
|
-
return useContext(ProfileColorContext);
|
|
39
|
-
}
|
|
40
|
-
function useProfileDisplayColor(hex) {
|
|
41
|
-
const preview = useProfileColorPreview();
|
|
42
|
-
return preview ? preview(hex) : hex;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
// src/ProfileChip.tsx
|
|
46
|
-
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
47
|
-
function ProfileChip({ profile, size = 22, filled = true }) {
|
|
48
|
-
const color = useProfileDisplayColor(profile.color);
|
|
49
|
-
return /* @__PURE__ */ jsx3(IdentityChip, { color, tag: profile.tag, icon: "account", size, filled });
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
// src/ProfilePicker.tsx
|
|
53
|
-
import { defaultColors, FadingScrollView, getContrastColor as getContrastColor2 } from "@rific/auto-paper";
|
|
54
|
-
import { TouchableRipple } from "@rific/feedback-press";
|
|
55
|
-
import { PopoverBody, useAutoAlign } from "@tastic/hud";
|
|
56
|
-
import { useMemo, useState } from "react";
|
|
57
|
-
import { StyleSheet as StyleSheet2, View as View2 } from "react-native";
|
|
58
|
-
import { Icon as Icon2, Text as Text2 } from "react-native-paper";
|
|
59
|
-
import { Fragment, jsx as jsx4, jsxs } from "react/jsx-runtime";
|
|
38
|
+
// src/PickerMenu.tsx
|
|
39
|
+
import { Fragment, jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
60
40
|
var TRIGGER_HEIGHT = 28;
|
|
61
41
|
var POPOVER_WIDTH = 220;
|
|
62
42
|
var ROW_HEIGHT = 36;
|
|
@@ -83,55 +63,37 @@ function colorPageHeight(swatches) {
|
|
|
83
63
|
const rows = Math.ceil(swatches.length / GRID_COLUMNS);
|
|
84
64
|
return ROW_HEIGHT + GRID_TOP + rows * SWATCH_SIZE + (rows - 1) * GRID_GAP + GRID_BOTTOM;
|
|
85
65
|
}
|
|
86
|
-
function
|
|
87
|
-
const rowCount = profileCount + 1 + (hasManageRow ? 1 : 0);
|
|
66
|
+
function pickerContentSize(rowCount, colorSection) {
|
|
88
67
|
const list = rowCount * ROW_HEIGHT + (colorSection ? colorRowHeight(colorSection.caption) + COLOR_ROW_DIVIDER : 0);
|
|
89
68
|
const content = colorSection ? Math.max(list, colorPageHeight(colorSection.swatches ?? defaultColors)) : list;
|
|
90
69
|
return { width: POPOVER_WIDTH, height: LIST_PADDING * 2 + content };
|
|
91
70
|
}
|
|
92
|
-
function
|
|
93
|
-
const id = `${idPrefix}-profile`;
|
|
94
|
-
const colorPreview = useProfileColorPreview();
|
|
71
|
+
function PickerMenu({ id, host, color, dark, label, chip, colorSection, homeColor, contentSize, align: forcedAlign, alignOverride, rotation, triggerStyle, footer, children }) {
|
|
95
72
|
const menuBg = dark ? "#000000" : "#FFFFFF";
|
|
96
73
|
const fg = dark ? "#FFFFFF" : "#000000";
|
|
97
74
|
const open = host.openId === id;
|
|
98
|
-
const
|
|
99
|
-
const sortedProfiles = useMemo(() => [...profiles].sort((a, b) => a.name.localeCompare(b.name)), [profiles]);
|
|
100
|
-
const { width: contentWidth, height: contentHeight } = getProfilePickerContentSize(profiles.length, !!onManage, colorSection);
|
|
101
|
-
const auto = useAutoAlign(open, contentWidth, contentHeight, rotation);
|
|
75
|
+
const auto = useAutoAlign(open, contentSize.width, contentSize.height, rotation);
|
|
102
76
|
const placement = alignOverride ?? auto;
|
|
103
77
|
const { maxHeight, measured, triggerRef, verticalAlign } = placement;
|
|
104
78
|
const align = forcedAlign ?? placement.align;
|
|
105
|
-
const
|
|
106
|
-
onSelect(null);
|
|
107
|
-
host.close();
|
|
108
|
-
};
|
|
109
|
-
const handleSelectExisting = (profile) => {
|
|
110
|
-
if (profile.id === takenId) return;
|
|
111
|
-
onSelect(profile);
|
|
112
|
-
host.close();
|
|
113
|
-
};
|
|
114
|
-
const handleManage = () => {
|
|
115
|
-
host.close();
|
|
116
|
-
onManage?.();
|
|
117
|
-
};
|
|
118
|
-
const chipTrigger = !!colorSection;
|
|
79
|
+
const chipTrigger = !!chip;
|
|
119
80
|
const [triggerWidth, setTriggerWidth] = useState(0);
|
|
120
81
|
const handleAnchorLayout = chipTrigger ? (e) => setTriggerWidth(e.nativeEvent.layout.width) : void 0;
|
|
121
82
|
const [colorPage, setColorPage] = useState(false);
|
|
83
|
+
const showColorPage = !!colorSection && colorPage;
|
|
122
84
|
const handleTriggerPress = () => {
|
|
123
85
|
setColorPage(false);
|
|
124
86
|
host.toggle(id);
|
|
125
87
|
};
|
|
126
|
-
const triggerLabel =
|
|
127
|
-
const
|
|
88
|
+
const triggerLabel = label.toUpperCase();
|
|
89
|
+
const showFooter = !!footer && !showColorPage;
|
|
128
90
|
return /* @__PURE__ */ jsxs(View2, { style: [styles2.anchor, open && styles2.anchorOpen], onLayout: handleAnchorLayout, children: [
|
|
129
|
-
/* @__PURE__ */
|
|
130
|
-
|
|
131
|
-
/* @__PURE__ */
|
|
132
|
-
/* @__PURE__ */
|
|
91
|
+
/* @__PURE__ */ jsx2(TouchableRipple, { onPress: handleTriggerPress, borderless: chipTrigger, style: [styles2.trigger, chipTrigger && styles2.chipTrigger, triggerStyle], accessibilityRole: "button", accessibilityLabel: triggerLabel, children: /* @__PURE__ */ jsxs(View2, { ref: triggerRef, collapsable: false, style: chipTrigger ? styles2.chipTriggerInner : styles2.triggerInner, children: [
|
|
92
|
+
chip && /* @__PURE__ */ jsx2(IdentityChip, { color, tag: chip.tag, icon: chip.icon, size: CHIP_SIZE }),
|
|
93
|
+
/* @__PURE__ */ jsx2(Text2, { style: [styles2.triggerLabel, { color: chipTrigger ? fg : color }], numberOfLines: 1, children: triggerLabel }),
|
|
94
|
+
/* @__PURE__ */ jsx2(Icon2, { source: "menu-down", size: 16, color: chipTrigger ? fg : color })
|
|
133
95
|
] }) }),
|
|
134
|
-
/* @__PURE__ */
|
|
96
|
+
/* @__PURE__ */ jsx2(PopoverBody, { visible: open && measured, align, verticalAlign, caretColor: menuBg, caretBorderColor: color, caretBorderWidth: MENU_BORDER_WIDTH, triggerSize: chipTrigger ? triggerWidth : TRIGGER_HEIGHT, children: /* @__PURE__ */ jsxs(
|
|
135
97
|
View2,
|
|
136
98
|
{
|
|
137
99
|
style: [
|
|
@@ -144,77 +106,81 @@ function ProfilePicker({ idPrefix, host, profiles, selectedId, takenId, color, d
|
|
|
144
106
|
}
|
|
145
107
|
],
|
|
146
108
|
children: [
|
|
147
|
-
/* @__PURE__ */
|
|
148
|
-
colorSection && /* @__PURE__ */
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
const taken = profile.id === takenId;
|
|
155
|
-
const selected = selectedId === profile.id;
|
|
156
|
-
const rowColor = colorPreview ? colorPreview(profile.color) : profile.color;
|
|
157
|
-
return /* @__PURE__ */ jsx4(TouchableRipple, { disabled: taken, onPress: () => handleSelectExisting(profile), style: [styles2.row, selected && { backgroundColor: rowColor }], children: /* @__PURE__ */ jsxs(View2, { style: [styles2.rowInner, taken && styles2.rowDisabled], children: [
|
|
158
|
-
/* @__PURE__ */ jsx4(ProfileChip, { profile, filled: !selected }),
|
|
159
|
-
/* @__PURE__ */ jsx4(
|
|
160
|
-
Text2,
|
|
161
|
-
{
|
|
162
|
-
style: [
|
|
163
|
-
styles2.rowLabel,
|
|
164
|
-
{
|
|
165
|
-
color: selected ? getContrastColor2(rowColor) : fg
|
|
166
|
-
}
|
|
167
|
-
],
|
|
168
|
-
numberOfLines: 1,
|
|
169
|
-
children: profile.name
|
|
170
|
-
}
|
|
171
|
-
)
|
|
172
|
-
] }) }, profile.id);
|
|
173
|
-
})
|
|
174
|
-
] }) }, colorSection && colorPage ? "color" : "list"),
|
|
175
|
-
manageFooter && /* @__PURE__ */ jsxs(View2, { style: styles2.menuFooter, children: [
|
|
176
|
-
/* @__PURE__ */ jsx4(View2, { style: [styles2.divider, { backgroundColor: color }] }),
|
|
177
|
-
/* @__PURE__ */ jsx4(TouchableRipple, { onPress: handleManage, style: styles2.row, children: /* @__PURE__ */ jsxs(View2, { style: styles2.manageRowInner, children: [
|
|
178
|
-
/* @__PURE__ */ jsx4(Icon2, { source: "account-cog-outline", size: 16, color }),
|
|
179
|
-
/* @__PURE__ */ jsx4(Text2, { style: [styles2.manageLabel, { color: fg }], children: "Manage" })
|
|
180
|
-
] }) })
|
|
109
|
+
/* @__PURE__ */ jsx2(FadingScrollView, { contentContainerStyle: [styles2.menuContent, showFooter && styles2.menuContentAboveFooter], showsVerticalScrollIndicator: false, children: colorSection && colorPage ? /* @__PURE__ */ jsx2(ColorPage, { section: colorSection, homeColor, fg, onBack: () => setColorPage(false) }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
110
|
+
colorSection && /* @__PURE__ */ jsx2(ColorRow, { section: colorSection, fg, dividerColor: color, onPress: () => setColorPage(true) }),
|
|
111
|
+
children
|
|
112
|
+
] }) }, showColorPage ? "color" : "list"),
|
|
113
|
+
showFooter && /* @__PURE__ */ jsxs(View2, { style: styles2.menuFooter, children: [
|
|
114
|
+
/* @__PURE__ */ jsx2(View2, { style: [styles2.divider, { backgroundColor: color }] }),
|
|
115
|
+
footer
|
|
181
116
|
] })
|
|
182
117
|
]
|
|
183
118
|
}
|
|
184
119
|
) })
|
|
185
120
|
] });
|
|
186
121
|
}
|
|
122
|
+
function IconRow({ icon, label, selected, color, fg, disabled = false, onPress }) {
|
|
123
|
+
const textColor = selected ? getContrastColor2(color) : fg;
|
|
124
|
+
return /* @__PURE__ */ jsx2(TouchableRipple, { disabled, onPress, style: [pickerMenuStyles.row, selected && { backgroundColor: color }], children: /* @__PURE__ */ jsxs(View2, { style: [pickerMenuStyles.rowInner, disabled && pickerMenuStyles.rowDisabled], children: [
|
|
125
|
+
/* @__PURE__ */ jsx2(View2, { style: styles2.iconSlot, children: /* @__PURE__ */ jsx2(Icon2, { source: icon, size: 13, color: textColor }) }),
|
|
126
|
+
/* @__PURE__ */ jsx2(Text2, { style: [pickerMenuStyles.rowLabel, { color: textColor }], numberOfLines: 1, children: label })
|
|
127
|
+
] }) });
|
|
128
|
+
}
|
|
187
129
|
function ColorRow({ section, fg, dividerColor, onPress }) {
|
|
188
130
|
const { value, previewValue, label = "Color", caption } = section;
|
|
189
131
|
const drawn = previewValue ? previewValue(value) : value;
|
|
190
132
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
191
|
-
/* @__PURE__ */
|
|
192
|
-
/* @__PURE__ */
|
|
133
|
+
/* @__PURE__ */ jsx2(TouchableRipple, { onPress, style: [pickerMenuStyles.row, { height: colorRowHeight(caption) }], accessibilityRole: "button", accessibilityLabel: caption ? `${label}, ${caption}` : label, children: /* @__PURE__ */ jsxs(View2, { style: pickerMenuStyles.rowInner, children: [
|
|
134
|
+
/* @__PURE__ */ jsx2(View2, { style: [styles2.colorRowSwatch, { backgroundColor: drawn }] }),
|
|
193
135
|
/* @__PURE__ */ jsxs(View2, { style: styles2.colorRowText, children: [
|
|
194
|
-
/* @__PURE__ */
|
|
195
|
-
caption ? /* @__PURE__ */
|
|
136
|
+
/* @__PURE__ */ jsx2(Text2, { style: [styles2.colorRowLabel, { color: fg }], numberOfLines: 1, children: label }),
|
|
137
|
+
caption ? /* @__PURE__ */ jsx2(Text2, { style: [styles2.colorRowCaption, { color: fg }], numberOfLines: 1, children: caption }) : null
|
|
196
138
|
] }),
|
|
197
|
-
/* @__PURE__ */
|
|
139
|
+
/* @__PURE__ */ jsx2(Icon2, { source: "chevron-right", size: 18, color: fg })
|
|
198
140
|
] }) }),
|
|
199
|
-
/* @__PURE__ */
|
|
141
|
+
/* @__PURE__ */ jsx2(View2, { style: [styles2.divider, { backgroundColor: dividerColor }] })
|
|
200
142
|
] });
|
|
201
143
|
}
|
|
202
|
-
function ColorPage({ section,
|
|
203
|
-
const { value, onChange, previewValue, swatches = defaultColors, label = "Color" } = section;
|
|
144
|
+
function ColorPage({ section, homeColor, fg, onBack }) {
|
|
145
|
+
const { value, onChange, previewValue, swatches = defaultColors, label = "Color", takenValue, allowSwapTaken } = section;
|
|
204
146
|
const displayFor = previewValue ?? ((hex) => hex);
|
|
205
147
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
206
|
-
/* @__PURE__ */
|
|
207
|
-
/* @__PURE__ */
|
|
208
|
-
/* @__PURE__ */
|
|
148
|
+
/* @__PURE__ */ jsx2(TouchableRipple, { onPress: onBack, style: pickerMenuStyles.row, accessibilityRole: "button", accessibilityLabel: "Back", children: /* @__PURE__ */ jsxs(View2, { style: pickerMenuStyles.rowInner, children: [
|
|
149
|
+
/* @__PURE__ */ jsx2(View2, { style: styles2.iconSlot, children: /* @__PURE__ */ jsx2(Icon2, { source: "chevron-left", size: 20, color: fg }) }),
|
|
150
|
+
/* @__PURE__ */ jsx2(Text2, { style: [styles2.colorRowLabel, { color: fg }], numberOfLines: 1, children: label })
|
|
209
151
|
] }) }),
|
|
210
|
-
/* @__PURE__ */
|
|
152
|
+
/* @__PURE__ */ jsx2(View2, { style: styles2.swatches, children: swatches.map((swatch) => {
|
|
211
153
|
const selected = swatch.value.toLowerCase() === value.toLowerCase();
|
|
212
|
-
const
|
|
154
|
+
const isHomeColor = !!homeColor && swatch.value.toLowerCase() === homeColor.toLowerCase();
|
|
155
|
+
const taken = !selected && !!takenValue && swatch.value.toLowerCase() === takenValue.toLowerCase();
|
|
156
|
+
const swappable = taken && !!allowSwapTaken;
|
|
213
157
|
const swatchDisplay = displayFor(swatch.value);
|
|
214
|
-
|
|
158
|
+
const contrast = getContrastColor2(swatchDisplay);
|
|
159
|
+
const accessibilityLabel = swappable ? `${swatch.label}, swap` : taken ? `${swatch.label}, taken` : isHomeColor ? `${swatch.label}, profile color` : swatch.label;
|
|
160
|
+
return /* @__PURE__ */ jsx2(TouchableRipple, { disabled: taken && !swappable, onPress: () => onChange(swatch.value), borderless: true, style: [styles2.swatch, { backgroundColor: swatchDisplay }, selected && styles2.swatchSelected, taken && !swappable && styles2.swatchTaken], accessibilityRole: "button", accessibilityLabel, accessibilityState: { selected, disabled: taken && !swappable }, children: selected ? /* @__PURE__ */ jsx2(Icon2, { source: "check", size: 16, color: contrast }) : swappable ? /* @__PURE__ */ jsx2(Icon2, { source: "swap-horizontal", size: 16, color: contrast }) : taken ? /* @__PURE__ */ jsx2(Icon2, { source: "close", size: 16, color: contrast }) : isHomeColor ? /* @__PURE__ */ jsx2(View2, { style: [styles2.homeDot, { backgroundColor: contrast }] }) : /* @__PURE__ */ jsx2(View2, {}) }, swatch.value);
|
|
215
161
|
}) })
|
|
216
162
|
] });
|
|
217
163
|
}
|
|
164
|
+
var pickerMenuStyles = StyleSheet2.create({
|
|
165
|
+
row: {
|
|
166
|
+
borderRadius: 8,
|
|
167
|
+
height: ROW_HEIGHT
|
|
168
|
+
},
|
|
169
|
+
rowDisabled: {
|
|
170
|
+
opacity: 0.35
|
|
171
|
+
},
|
|
172
|
+
rowInner: {
|
|
173
|
+
alignItems: "center",
|
|
174
|
+
flexDirection: "row",
|
|
175
|
+
flex: 1,
|
|
176
|
+
gap: 8,
|
|
177
|
+
paddingHorizontal: ROW_INSET
|
|
178
|
+
},
|
|
179
|
+
rowLabel: {
|
|
180
|
+
flex: 1,
|
|
181
|
+
fontSize: 14
|
|
182
|
+
}
|
|
183
|
+
});
|
|
218
184
|
var styles2 = StyleSheet2.create({
|
|
219
185
|
anchor: {
|
|
220
186
|
position: "relative"
|
|
@@ -258,38 +224,31 @@ var styles2 = StyleSheet2.create({
|
|
|
258
224
|
colorRowText: {
|
|
259
225
|
flex: 1
|
|
260
226
|
},
|
|
261
|
-
// Separates
|
|
262
|
-
// action, not just another row in the same list. Tinted with the seat's own color
|
|
263
|
-
// backgroundColor) rather than a flat gray, matching the border/caret's own
|
|
227
|
+
// Separates the footer (a navigation action) and the Color row from the selectable rows - a
|
|
228
|
+
// different kind of action, not just another row in the same list. Tinted with the seat's own color
|
|
229
|
+
// (passed in as backgroundColor) rather than a flat gray, matching the border/caret's own
|
|
230
|
+
// accent-tinted look.
|
|
264
231
|
divider: {
|
|
265
232
|
height: 1,
|
|
266
233
|
marginVertical: 4,
|
|
267
234
|
opacity: 0.25
|
|
268
235
|
},
|
|
269
|
-
//
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
236
|
+
// The selected profile's own color (see ColorPage).
|
|
237
|
+
homeDot: {
|
|
238
|
+
borderRadius: 4,
|
|
239
|
+
height: 8,
|
|
240
|
+
width: 8
|
|
241
|
+
},
|
|
242
|
+
// Matches ProfileChip's own default size/shape exactly (see IconRow's own render-site comment) -
|
|
243
|
+
// no backgroundColor, unlike ProfileChip's own default: an icon row has no identity color of its
|
|
244
|
+
// own to fill it with, and the render site colors the icon directly instead.
|
|
245
|
+
iconSlot: {
|
|
273
246
|
alignItems: "center",
|
|
274
247
|
borderRadius: 11,
|
|
275
248
|
height: 22,
|
|
276
249
|
justifyContent: "center",
|
|
277
250
|
width: 22
|
|
278
251
|
},
|
|
279
|
-
manageLabel: {
|
|
280
|
-
fontSize: 13,
|
|
281
|
-
fontWeight: "700",
|
|
282
|
-
letterSpacing: 0.5
|
|
283
|
-
},
|
|
284
|
-
// Centered rather than left-aligned like a normal row - see this row's own render-site comment
|
|
285
|
-
// for why (a footer action, not another selectable identity).
|
|
286
|
-
manageRowInner: {
|
|
287
|
-
alignItems: "center",
|
|
288
|
-
flexDirection: "row",
|
|
289
|
-
gap: 6,
|
|
290
|
-
height: "100%",
|
|
291
|
-
justifyContent: "center"
|
|
292
|
-
},
|
|
293
252
|
menu: {
|
|
294
253
|
borderRadius: 12,
|
|
295
254
|
borderWidth: MENU_BORDER_WIDTH,
|
|
@@ -305,7 +264,7 @@ var styles2 = StyleSheet2.create({
|
|
|
305
264
|
menuContent: {
|
|
306
265
|
padding: LIST_PADDING
|
|
307
266
|
},
|
|
308
|
-
// With
|
|
267
|
+
// With a footer pinned below, its own padding takes the bottom edge (same total height as before).
|
|
309
268
|
menuContentAboveFooter: {
|
|
310
269
|
paddingBottom: 0
|
|
311
270
|
},
|
|
@@ -313,30 +272,6 @@ var styles2 = StyleSheet2.create({
|
|
|
313
272
|
paddingBottom: LIST_PADDING,
|
|
314
273
|
paddingHorizontal: LIST_PADDING
|
|
315
274
|
},
|
|
316
|
-
// The selected profile's own color (see ColorSection).
|
|
317
|
-
profileDot: {
|
|
318
|
-
borderRadius: 4,
|
|
319
|
-
height: 8,
|
|
320
|
-
width: 8
|
|
321
|
-
},
|
|
322
|
-
row: {
|
|
323
|
-
borderRadius: 8,
|
|
324
|
-
height: ROW_HEIGHT
|
|
325
|
-
},
|
|
326
|
-
rowDisabled: {
|
|
327
|
-
opacity: 0.35
|
|
328
|
-
},
|
|
329
|
-
rowInner: {
|
|
330
|
-
alignItems: "center",
|
|
331
|
-
flexDirection: "row",
|
|
332
|
-
flex: 1,
|
|
333
|
-
gap: 8,
|
|
334
|
-
paddingHorizontal: ROW_INSET
|
|
335
|
-
},
|
|
336
|
-
rowLabel: {
|
|
337
|
-
flex: 1,
|
|
338
|
-
fontSize: 14
|
|
339
|
-
},
|
|
340
275
|
swatch: {
|
|
341
276
|
alignItems: "center",
|
|
342
277
|
borderRadius: SWATCH_SIZE / 2,
|
|
@@ -348,6 +283,9 @@ var styles2 = StyleSheet2.create({
|
|
|
348
283
|
borderColor: "#ffffff",
|
|
349
284
|
borderWidth: 2
|
|
350
285
|
},
|
|
286
|
+
swatchTaken: {
|
|
287
|
+
opacity: 0.35
|
|
288
|
+
},
|
|
351
289
|
swatches: {
|
|
352
290
|
columnGap: GRID_GAP,
|
|
353
291
|
flexDirection: "row",
|
|
@@ -374,15 +312,128 @@ var styles2 = StyleSheet2.create({
|
|
|
374
312
|
}
|
|
375
313
|
});
|
|
376
314
|
|
|
377
|
-
// src/
|
|
378
|
-
import {
|
|
315
|
+
// src/OptionPicker.tsx
|
|
316
|
+
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
317
|
+
function getOptionPickerContentSize(optionCount, colorSection) {
|
|
318
|
+
return pickerContentSize(optionCount, colorSection);
|
|
319
|
+
}
|
|
320
|
+
function OptionPicker({ id, host, options, value, onChange, color, dark, icon, rowIcon = icon, colorSection, align, alignOverride, rotation = 0, triggerStyle }) {
|
|
321
|
+
const fg = dark ? "#FFFFFF" : "#000000";
|
|
322
|
+
const selected = options.find((option) => option.value === value);
|
|
323
|
+
const handleSelect = (option) => {
|
|
324
|
+
onChange(option.value);
|
|
325
|
+
host.close();
|
|
326
|
+
};
|
|
327
|
+
return /* @__PURE__ */ jsx3(PickerMenu, { id, host, color, dark, label: selected?.label ?? "", chip: { icon }, colorSection, contentSize: getOptionPickerContentSize(options.length, colorSection), align, alignOverride, rotation, triggerStyle, children: options.map((option) => /* @__PURE__ */ jsx3(IconRow, { icon: option.icon ?? rowIcon, label: option.label, selected: option.value === value, color, fg, onPress: () => handleSelect(option) }, option.value)) });
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
// src/ProfileColorContext.tsx
|
|
331
|
+
import { createContext, useContext } from "react";
|
|
332
|
+
import { jsx as jsx4 } from "react/jsx-runtime";
|
|
333
|
+
var ProfileColorContext = createContext(void 0);
|
|
334
|
+
function ProfileColorProvider({ preview, children }) {
|
|
335
|
+
return /* @__PURE__ */ jsx4(ProfileColorContext.Provider, { value: preview, children });
|
|
336
|
+
}
|
|
337
|
+
function useProfileColorPreview() {
|
|
338
|
+
return useContext(ProfileColorContext);
|
|
339
|
+
}
|
|
340
|
+
function useProfileDisplayColor(hex) {
|
|
341
|
+
const preview = useProfileColorPreview();
|
|
342
|
+
return preview ? preview(hex) : hex;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
// src/ProfileChip.tsx
|
|
346
|
+
import { jsx as jsx5 } from "react/jsx-runtime";
|
|
347
|
+
function ProfileChip({ profile, size = 22, filled = true }) {
|
|
348
|
+
const color = useProfileDisplayColor(profile.color);
|
|
349
|
+
return /* @__PURE__ */ jsx5(IdentityChip, { color, tag: profile.tag, icon: "account", size, filled });
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
// src/ProfilePicker.tsx
|
|
353
|
+
import { getContrastColor as getContrastColor3 } from "@rific/auto-paper";
|
|
379
354
|
import { TouchableRipple as TouchableRipple2 } from "@rific/feedback-press";
|
|
355
|
+
import { useMemo } from "react";
|
|
356
|
+
import { StyleSheet as StyleSheet3, View as View3 } from "react-native";
|
|
357
|
+
import { Icon as Icon3, Text as Text3 } from "react-native-paper";
|
|
358
|
+
import { jsx as jsx6, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
359
|
+
function getProfilePickerContentSize(profileCount, hasManageRow = false, colorSection) {
|
|
360
|
+
return pickerContentSize(profileCount + 1 + (hasManageRow ? 1 : 0), colorSection);
|
|
361
|
+
}
|
|
362
|
+
function ProfilePicker({ idPrefix, host, profiles, selectedId, takenId, color, dark, align, alignOverride, rotation = 0, guestLabel, nullLabel = "Player", nullIcon = "account-off-outline", onSelect, onManage, colorSection, triggerStyle }) {
|
|
363
|
+
const id = `${idPrefix}-profile`;
|
|
364
|
+
const colorPreview = useProfileColorPreview();
|
|
365
|
+
const fg = dark ? "#FFFFFF" : "#000000";
|
|
366
|
+
const selectedProfile = profiles.find((p) => p.id === selectedId) ?? null;
|
|
367
|
+
const sortedProfiles = useMemo(() => [...profiles].sort((a, b) => a.name.localeCompare(b.name)), [profiles]);
|
|
368
|
+
const contentSize = getProfilePickerContentSize(profiles.length, !!onManage, colorSection);
|
|
369
|
+
const handleSelectGuest = () => {
|
|
370
|
+
onSelect(null);
|
|
371
|
+
host.close();
|
|
372
|
+
};
|
|
373
|
+
const handleSelectExisting = (profile) => {
|
|
374
|
+
if (profile.id === takenId) return;
|
|
375
|
+
onSelect(profile);
|
|
376
|
+
host.close();
|
|
377
|
+
};
|
|
378
|
+
const handleManage = () => {
|
|
379
|
+
host.close();
|
|
380
|
+
onManage?.();
|
|
381
|
+
};
|
|
382
|
+
const manageFooter = onManage ? /* @__PURE__ */ jsx6(TouchableRipple2, { onPress: handleManage, style: pickerMenuStyles.row, children: /* @__PURE__ */ jsxs2(View3, { style: styles3.manageRowInner, children: [
|
|
383
|
+
/* @__PURE__ */ jsx6(Icon3, { source: "account-cog-outline", size: 16, color }),
|
|
384
|
+
/* @__PURE__ */ jsx6(Text3, { style: [styles3.manageLabel, { color: fg }], children: "Manage" })
|
|
385
|
+
] }) }) : void 0;
|
|
386
|
+
return /* @__PURE__ */ jsxs2(PickerMenu, { id, host, color, dark, label: selectedProfile?.name ?? guestLabel, chip: colorSection ? { tag: selectedProfile?.tag, icon: selectedProfile ? "account" : nullIcon } : void 0, colorSection, homeColor: selectedProfile?.color, contentSize, align, alignOverride, rotation, triggerStyle, footer: manageFooter, children: [
|
|
387
|
+
/* @__PURE__ */ jsx6(IconRow, { icon: nullIcon, label: nullLabel, selected: selectedId === null, color, fg, onPress: handleSelectGuest }),
|
|
388
|
+
sortedProfiles.map((profile) => {
|
|
389
|
+
const taken = profile.id === takenId;
|
|
390
|
+
const selected = selectedId === profile.id;
|
|
391
|
+
const rowColor = colorPreview ? colorPreview(profile.color) : profile.color;
|
|
392
|
+
return /* @__PURE__ */ jsx6(TouchableRipple2, { disabled: taken, onPress: () => handleSelectExisting(profile), style: [pickerMenuStyles.row, selected && { backgroundColor: rowColor }], children: /* @__PURE__ */ jsxs2(View3, { style: [pickerMenuStyles.rowInner, taken && pickerMenuStyles.rowDisabled], children: [
|
|
393
|
+
/* @__PURE__ */ jsx6(ProfileChip, { profile, filled: !selected }),
|
|
394
|
+
/* @__PURE__ */ jsx6(
|
|
395
|
+
Text3,
|
|
396
|
+
{
|
|
397
|
+
style: [
|
|
398
|
+
pickerMenuStyles.rowLabel,
|
|
399
|
+
{
|
|
400
|
+
color: selected ? getContrastColor3(rowColor) : fg
|
|
401
|
+
}
|
|
402
|
+
],
|
|
403
|
+
numberOfLines: 1,
|
|
404
|
+
children: profile.name
|
|
405
|
+
}
|
|
406
|
+
)
|
|
407
|
+
] }) }, profile.id);
|
|
408
|
+
})
|
|
409
|
+
] });
|
|
410
|
+
}
|
|
411
|
+
var styles3 = StyleSheet3.create({
|
|
412
|
+
manageLabel: {
|
|
413
|
+
fontSize: 13,
|
|
414
|
+
fontWeight: "700",
|
|
415
|
+
letterSpacing: 0.5
|
|
416
|
+
},
|
|
417
|
+
// Centered rather than left-aligned like a normal row - see the footer's own comment for why (a
|
|
418
|
+
// footer action, not another selectable identity).
|
|
419
|
+
manageRowInner: {
|
|
420
|
+
alignItems: "center",
|
|
421
|
+
flexDirection: "row",
|
|
422
|
+
gap: 6,
|
|
423
|
+
height: "100%",
|
|
424
|
+
justifyContent: "center"
|
|
425
|
+
}
|
|
426
|
+
});
|
|
427
|
+
|
|
428
|
+
// src/ProfilesManager.tsx
|
|
429
|
+
import { defaultColors as defaultColors2, FadingScrollView as FadingScrollView2, useAutoPaperTheme } from "@rific/auto-paper";
|
|
430
|
+
import { TouchableRipple as TouchableRipple3 } from "@rific/feedback-press";
|
|
380
431
|
import { useFocusChain } from "@rific/focus-chain";
|
|
381
432
|
import { useToast } from "@rific/toaster";
|
|
382
433
|
import { ConfirmDialog, getInlineColorPickerContentSize, InlineColorPicker, usePopoverHost } from "@tastic/hud";
|
|
383
434
|
import { useCallback, useEffect, useImperativeHandle, useMemo as useMemo2, useRef, useState as useState2 } from "react";
|
|
384
|
-
import { KeyboardAvoidingView, Platform,
|
|
385
|
-
import { Icon as
|
|
435
|
+
import { KeyboardAvoidingView, Platform, StyleSheet as StyleSheet4, useWindowDimensions, View as View4 } from "react-native";
|
|
436
|
+
import { Icon as Icon4, Text as Text4, TextInput } from "react-native-paper";
|
|
386
437
|
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
|
387
438
|
|
|
388
439
|
// src/profilesValidation.ts
|
|
@@ -418,7 +469,7 @@ function isValidProfile(value) {
|
|
|
418
469
|
}
|
|
419
470
|
|
|
420
471
|
// src/ProfilesManager.tsx
|
|
421
|
-
import { Fragment as Fragment2, jsx as
|
|
472
|
+
import { Fragment as Fragment2, jsx as jsx7, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
422
473
|
var CHIP_SIZE2 = 40;
|
|
423
474
|
function deriveTag(name) {
|
|
424
475
|
const trimmed = name.trim();
|
|
@@ -495,38 +546,38 @@ function ProfilesManager({ profiles, defaultColor, onCreate, onSave, onDelete, h
|
|
|
495
546
|
}, [confirmDeleteId, editingId, onDelete]);
|
|
496
547
|
const sortedProfiles = useMemo2(() => [...profiles].sort((a, b) => a.name.localeCompare(b.name)), [profiles]);
|
|
497
548
|
const rows = [...sortedProfiles.map((profile) => ({ kind: "profile", profile })), { kind: "new" }];
|
|
498
|
-
return /* @__PURE__ */
|
|
499
|
-
/* @__PURE__ */
|
|
549
|
+
return /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
550
|
+
/* @__PURE__ */ jsxs3(View4, { style: [styles4.header, { paddingTop: 8 + insets.top, paddingLeft: 8 + insets.left }], children: [
|
|
500
551
|
headerLeft,
|
|
501
|
-
/* @__PURE__ */
|
|
552
|
+
/* @__PURE__ */ jsx7(Text4, { variant: titleVariant, style: [styles4.title, { color: fg }], children: "Profiles" })
|
|
502
553
|
] }),
|
|
503
|
-
/* @__PURE__ */
|
|
554
|
+
/* @__PURE__ */ jsx7(KeyboardAvoidingView, { behavior: Platform.OS === "ios" ? "padding" : void 0, style: styles4.keyboardAvoiding, children: /* @__PURE__ */ jsx7(FadingScrollView2, { style: styles4.scrollView, contentContainerStyle: [styles4.content, { paddingBottom: 32 + insets.bottom }], showsVerticalScrollIndicator: false, keyboardShouldPersistTaps: "handled", children: rows.map((row) => {
|
|
504
555
|
if (row.kind === "new") {
|
|
505
556
|
if (editingId !== "new") {
|
|
506
|
-
return /* @__PURE__ */
|
|
507
|
-
/* @__PURE__ */
|
|
508
|
-
/* @__PURE__ */
|
|
557
|
+
return /* @__PURE__ */ jsx7(TouchableRipple3, { onPress: () => startEdit("new"), style: styles4.row, children: /* @__PURE__ */ jsxs3(View4, { style: styles4.rowInner, children: [
|
|
558
|
+
/* @__PURE__ */ jsx7(View4, { style: [styles4.rowChip, styles4.newChip, { borderColor: fg }], children: /* @__PURE__ */ jsx7(Icon4, { source: "plus", size: 20, color: fg }) }),
|
|
559
|
+
/* @__PURE__ */ jsx7(Text4, { variant: "bodyLarge", style: { color: fg }, children: "New Profile" })
|
|
509
560
|
] }) }, "new");
|
|
510
561
|
}
|
|
511
|
-
return /* @__PURE__ */
|
|
562
|
+
return /* @__PURE__ */ jsx7(EditRow, { draftName, onNameChange: handleNameChange, draftColor, onColorChange: setDraftColor, draftTag, onTagChange: handleTagChange, onSubmit: commitEdit, autoFocus: true, fgMuted, host, dark, colorPreview, useColorPickerAlign }, "new");
|
|
512
563
|
}
|
|
513
564
|
const { profile } = row;
|
|
514
565
|
if (editingId === profile.id) {
|
|
515
|
-
return /* @__PURE__ */
|
|
566
|
+
return /* @__PURE__ */ jsx7(EditRow, { draftName, onNameChange: handleNameChange, draftColor, onColorChange: setDraftColor, draftTag, onTagChange: handleTagChange, onSubmit: commitEdit, onDelete: () => setConfirmDeleteId(profile.id), fgMuted, host, dark, colorPreview, useColorPickerAlign }, profile.id);
|
|
516
567
|
}
|
|
517
|
-
return /* @__PURE__ */
|
|
518
|
-
/* @__PURE__ */
|
|
519
|
-
/* @__PURE__ */
|
|
568
|
+
return /* @__PURE__ */ jsx7(TouchableRipple3, { onPress: () => startEdit(profile), style: styles4.row, children: /* @__PURE__ */ jsxs3(View4, { style: styles4.rowInner, children: [
|
|
569
|
+
/* @__PURE__ */ jsx7(ProfileChip, { profile, size: CHIP_SIZE2 }),
|
|
570
|
+
/* @__PURE__ */ jsx7(Text4, { variant: "bodyLarge", style: [styles4.rowName, { color: fg }], numberOfLines: 1, children: profile.name })
|
|
520
571
|
] }) }, profile.id);
|
|
521
572
|
}) }) }),
|
|
522
|
-
/* @__PURE__ */
|
|
573
|
+
/* @__PURE__ */ jsx7(ConfirmDialog, { visible: confirmDeleteProfile !== null, title: "Delete Profile?", message: confirmDeleteProfile ? `This permanently deletes ${confirmDeleteProfile.name}\u2019s profile. This cannot be undone.` : "", confirmLabel: "Delete", cancelLabel: "Cancel", icon: "alert-outline", destructive: true, onConfirm: handleConfirmDelete, onCancel: () => setConfirmDeleteId(null) })
|
|
523
574
|
] });
|
|
524
575
|
}
|
|
525
576
|
function AlignedColorPicker({ useAlign, ...props }) {
|
|
526
577
|
const { width: windowWidth } = useWindowDimensions();
|
|
527
578
|
const { width, height } = getInlineColorPickerContentSize(defaultColors2.length, windowWidth);
|
|
528
579
|
const alignOverride = useAlign(props.host.openId === props.id, width, height);
|
|
529
|
-
return /* @__PURE__ */
|
|
580
|
+
return /* @__PURE__ */ jsx7(InlineColorPicker, { ...props, alignOverride });
|
|
530
581
|
}
|
|
531
582
|
function EditRow({ draftName, onNameChange, draftColor, onColorChange, draftTag, onTagChange, onSubmit, onDelete, autoFocus, fgMuted, host, dark, colorPreview, useColorPickerAlign }) {
|
|
532
583
|
const register = useFocusChain();
|
|
@@ -539,14 +590,14 @@ function EditRow({ draftName, onNameChange, draftColor, onColorChange, draftTag,
|
|
|
539
590
|
useEffect(() => {
|
|
540
591
|
if (host.openId === "color") tagFocusRef.current();
|
|
541
592
|
}, [host.openId]);
|
|
542
|
-
return /* @__PURE__ */
|
|
543
|
-
useColorPickerAlign ? /* @__PURE__ */
|
|
544
|
-
/* @__PURE__ */
|
|
545
|
-
/* @__PURE__ */
|
|
546
|
-
onDelete && /* @__PURE__ */
|
|
593
|
+
return /* @__PURE__ */ jsxs3(View4, { style: styles4.editRow, children: [
|
|
594
|
+
useColorPickerAlign ? /* @__PURE__ */ jsx7(AlignedColorPicker, { useAlign: useColorPickerAlign, id: "color", host, value: draftColor, onChange: onColorChange, previewValue: colorPreview, tag: draftTag, dark }) : /* @__PURE__ */ jsx7(InlineColorPicker, { id: "color", host, value: draftColor, onChange: onColorChange, previewValue: colorPreview, tag: draftTag, dark }),
|
|
595
|
+
/* @__PURE__ */ jsx7(TextInput, { ref: tag.ref, ...tag.props, value: draftTag, onChangeText: onTagChange, accessibilityLabel: "Tag", autoCapitalize: "characters", selectTextOnFocus: true, returnKeyType: "next", style: styles4.hiddenTagInput, pointerEvents: "none" }),
|
|
596
|
+
/* @__PURE__ */ jsx7(TextInput, { ref: name.ref, ...name.props, onSubmitEditing: onSubmit, mode: "outlined", dense: true, value: draftName, onChangeText: onNameChange, maxLength: MAX_PROFILE_NAME_LENGTH, placeholder: "Name", autoFocus, returnKeyType: "done", style: styles4.nameInput }),
|
|
597
|
+
onDelete && /* @__PURE__ */ jsx7(TouchableRipple3, { onPress: onDelete, style: styles4.iconButton, children: /* @__PURE__ */ jsx7(Icon4, { source: "trash-can-outline", size: 18, color: fgMuted }) })
|
|
547
598
|
] });
|
|
548
599
|
}
|
|
549
|
-
var
|
|
600
|
+
var styles4 = StyleSheet4.create({
|
|
550
601
|
content: {
|
|
551
602
|
gap: 4,
|
|
552
603
|
paddingHorizontal: 20
|
|
@@ -628,8 +679,8 @@ var styles3 = StyleSheet3.create({
|
|
|
628
679
|
import { useAutoPaperTheme as useAutoPaperTheme2 } from "@rific/auto-paper";
|
|
629
680
|
import { IconButton } from "@rific/feedback-press";
|
|
630
681
|
import { useRef as useRef2 } from "react";
|
|
631
|
-
import { StyleSheet as
|
|
632
|
-
import { jsx as
|
|
682
|
+
import { StyleSheet as StyleSheet5, View as View5 } from "react-native";
|
|
683
|
+
import { jsx as jsx8 } from "react/jsx-runtime";
|
|
633
684
|
function ProfilesScreen({ profiles, defaultColor, onCreate, onSave, onDelete, onBack, fg: fgOverride, fgMuted, bg: bgOverride, titleVariant, colorPreview, useColorPickerAlign }) {
|
|
634
685
|
const { dark } = useAutoPaperTheme2();
|
|
635
686
|
const managerRef = useRef2(null);
|
|
@@ -639,9 +690,9 @@ function ProfilesScreen({ profiles, defaultColor, onCreate, onSave, onDelete, on
|
|
|
639
690
|
managerRef.current?.commitPendingEdit();
|
|
640
691
|
onBack();
|
|
641
692
|
};
|
|
642
|
-
return /* @__PURE__ */
|
|
693
|
+
return /* @__PURE__ */ jsx8(View5, { style: [styles5.container, { backgroundColor: bg }], children: /* @__PURE__ */ jsx8(ProfilesManager, { ref: managerRef, profiles, defaultColor, onCreate, onSave, onDelete, fg, fgMuted, titleVariant, colorPreview, useColorPickerAlign, headerLeft: /* @__PURE__ */ jsx8(IconButton, { icon: "arrow-left", iconColor: fg, size: 24, onPress: handleBack, accessibilityLabel: "Back" }) }) });
|
|
643
694
|
}
|
|
644
|
-
var
|
|
695
|
+
var styles5 = StyleSheet5.create({
|
|
645
696
|
container: {
|
|
646
697
|
flex: 1
|
|
647
698
|
}
|
|
@@ -805,21 +856,52 @@ async function resolveInitialProfiles(groupId, localFallback) {
|
|
|
805
856
|
|
|
806
857
|
// src/redux/seatColorsSlice.ts
|
|
807
858
|
var REHYDRATE2 = "persist/REHYDRATE";
|
|
859
|
+
function sameColor(a, b) {
|
|
860
|
+
return a.toLowerCase() === b.toLowerCase();
|
|
861
|
+
}
|
|
862
|
+
function profileSeatColor(profile, profileColors) {
|
|
863
|
+
const pick = profileColors[profile.id];
|
|
864
|
+
return pick && sameColor(pick.profileColor, profile.color) ? pick.color : profile.color;
|
|
865
|
+
}
|
|
808
866
|
function createSeatColorsSlice(namespace, defaultState, mountKey = "seatColors") {
|
|
809
867
|
const setLastCpuColor = createActionCreator(`seatColors/${namespace}/setLastCpuColor`);
|
|
810
868
|
const setLastGuestColor = createActionCreator(`seatColors/${namespace}/setLastGuestColor`);
|
|
811
|
-
const
|
|
869
|
+
const setProfileColor = createActionCreator(`seatColors/${namespace}/setProfileColor`);
|
|
870
|
+
function withoutPick(state, id) {
|
|
871
|
+
if (!state.profileColors[id]) return state;
|
|
872
|
+
const profileColors = { ...state.profileColors };
|
|
873
|
+
delete profileColors[id];
|
|
874
|
+
return { ...state, profileColors };
|
|
875
|
+
}
|
|
812
876
|
function reducer(state = defaultState, action) {
|
|
813
877
|
if (action.type === REHYDRATE2) {
|
|
814
878
|
const persisted = action.payload?.[mountKey];
|
|
815
|
-
|
|
879
|
+
const next = { ...defaultState, ...state, ...persisted };
|
|
880
|
+
delete next.profileOverride;
|
|
881
|
+
return next;
|
|
816
882
|
}
|
|
817
883
|
if (setLastCpuColor.match(action)) return { ...state, lastCpuColor: action.payload };
|
|
818
884
|
if (setLastGuestColor.match(action)) return { ...state, lastGuestColor: { ...state.lastGuestColor, [action.payload.seat]: action.payload.color } };
|
|
819
|
-
if (
|
|
885
|
+
if (setProfileColor.match(action)) {
|
|
886
|
+
const { profile, color } = action.payload;
|
|
887
|
+
if (color === null || sameColor(color, profile.color)) return withoutPick(state, profile.id);
|
|
888
|
+
return { ...state, profileColors: { ...state.profileColors, [profile.id]: { color, profileColor: profile.color } } };
|
|
889
|
+
}
|
|
890
|
+
if (profilesActions.remove.match(action)) return withoutPick(state, action.payload);
|
|
891
|
+
if (profilesActions.update.match(action)) {
|
|
892
|
+
const { id, patch } = action.payload;
|
|
893
|
+
const pick = state.profileColors[id];
|
|
894
|
+
return pick && patch.color !== void 0 && !sameColor(patch.color, pick.profileColor) ? withoutPick(state, id) : state;
|
|
895
|
+
}
|
|
896
|
+
if (profilesActions.setAll.match(action)) {
|
|
897
|
+
return action.payload.reduce((next, profile) => {
|
|
898
|
+
const pick = next.profileColors[profile.id];
|
|
899
|
+
return pick && !sameColor(profile.color, pick.profileColor) ? withoutPick(next, profile.id) : next;
|
|
900
|
+
}, state);
|
|
901
|
+
}
|
|
820
902
|
return state;
|
|
821
903
|
}
|
|
822
|
-
return { actions: { setLastCpuColor, setLastGuestColor,
|
|
904
|
+
return { actions: { setLastCpuColor, setLastGuestColor, setProfileColor }, reducer };
|
|
823
905
|
}
|
|
824
906
|
|
|
825
907
|
// src/redux/useSharedProfilesSync.ts
|
|
@@ -868,6 +950,7 @@ function avoidSeatColorClash(p1Color, p2Color, defaults) {
|
|
|
868
950
|
export {
|
|
869
951
|
MAX_PROFILE_NAME_LENGTH,
|
|
870
952
|
MAX_TAG_LENGTH,
|
|
953
|
+
OptionPicker,
|
|
871
954
|
ProfileChip,
|
|
872
955
|
ProfileColorProvider,
|
|
873
956
|
ProfilePicker,
|
|
@@ -878,11 +961,13 @@ export {
|
|
|
878
961
|
createProfileRecord,
|
|
879
962
|
createProfileSelectionSlice,
|
|
880
963
|
createSeatColorsSlice,
|
|
964
|
+
getOptionPickerContentSize,
|
|
881
965
|
getProfilePickerContentSize,
|
|
882
966
|
isSharedProfileStoreAvailable,
|
|
883
967
|
isValidProfile,
|
|
884
968
|
isValidTag,
|
|
885
969
|
loadSharedProfiles,
|
|
970
|
+
profileSeatColor,
|
|
886
971
|
profilesActions,
|
|
887
972
|
profilesReducer,
|
|
888
973
|
readSharedProfiles,
|