@tastic/profile 0.14.0 → 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 +322 -223
- package/dist/index.mjs +279 -183
- package/package.json +8 -8
- package/src/OptionPicker.tsx +64 -0
- package/src/PickerMenu.tsx +481 -0
- package/src/ProfilePicker.tsx +54 -413
- 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,54 +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 =
|
|
88
|
+
const triggerLabel = label.toUpperCase();
|
|
89
|
+
const showFooter = !!footer && !showColorPage;
|
|
127
90
|
return /* @__PURE__ */ jsxs(View2, { style: [styles2.anchor, open && styles2.anchorOpen], onLayout: handleAnchorLayout, children: [
|
|
128
|
-
/* @__PURE__ */
|
|
129
|
-
|
|
130
|
-
/* @__PURE__ */
|
|
131
|
-
/* @__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 })
|
|
132
95
|
] }) }),
|
|
133
|
-
/* @__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(
|
|
134
97
|
View2,
|
|
135
98
|
{
|
|
136
99
|
style: [
|
|
@@ -142,76 +105,82 @@ function ProfilePicker({ idPrefix, host, profiles, selectedId, takenId, color, d
|
|
|
142
105
|
maxHeight
|
|
143
106
|
}
|
|
144
107
|
],
|
|
145
|
-
children:
|
|
146
|
-
colorSection && /* @__PURE__ */
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
const selected = selectedId === profile.id;
|
|
154
|
-
const rowColor = colorPreview ? colorPreview(profile.color) : profile.color;
|
|
155
|
-
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: [
|
|
156
|
-
/* @__PURE__ */ jsx4(ProfileChip, { profile, filled: !selected }),
|
|
157
|
-
/* @__PURE__ */ jsx4(
|
|
158
|
-
Text2,
|
|
159
|
-
{
|
|
160
|
-
style: [
|
|
161
|
-
styles2.rowLabel,
|
|
162
|
-
{
|
|
163
|
-
color: selected ? getContrastColor2(rowColor) : fg
|
|
164
|
-
}
|
|
165
|
-
],
|
|
166
|
-
numberOfLines: 1,
|
|
167
|
-
children: profile.name
|
|
168
|
-
}
|
|
169
|
-
)
|
|
170
|
-
] }) }, profile.id);
|
|
171
|
-
}),
|
|
172
|
-
onManage && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
173
|
-
/* @__PURE__ */ jsx4(View2, { style: [styles2.divider, { backgroundColor: color }] }),
|
|
174
|
-
/* @__PURE__ */ jsx4(TouchableRipple, { onPress: handleManage, style: styles2.row, children: /* @__PURE__ */ jsxs(View2, { style: styles2.manageRowInner, children: [
|
|
175
|
-
/* @__PURE__ */ jsx4(Icon2, { source: "account-cog-outline", size: 16, color }),
|
|
176
|
-
/* @__PURE__ */ jsx4(Text2, { style: [styles2.manageLabel, { color: fg }], children: "Manage" })
|
|
177
|
-
] }) })
|
|
108
|
+
children: [
|
|
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
|
|
178
116
|
] })
|
|
179
|
-
]
|
|
117
|
+
]
|
|
180
118
|
}
|
|
181
119
|
) })
|
|
182
120
|
] });
|
|
183
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
|
+
}
|
|
184
129
|
function ColorRow({ section, fg, dividerColor, onPress }) {
|
|
185
130
|
const { value, previewValue, label = "Color", caption } = section;
|
|
186
131
|
const drawn = previewValue ? previewValue(value) : value;
|
|
187
132
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
188
|
-
/* @__PURE__ */
|
|
189
|
-
/* @__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 }] }),
|
|
190
135
|
/* @__PURE__ */ jsxs(View2, { style: styles2.colorRowText, children: [
|
|
191
|
-
/* @__PURE__ */
|
|
192
|
-
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
|
|
193
138
|
] }),
|
|
194
|
-
/* @__PURE__ */
|
|
139
|
+
/* @__PURE__ */ jsx2(Icon2, { source: "chevron-right", size: 18, color: fg })
|
|
195
140
|
] }) }),
|
|
196
|
-
/* @__PURE__ */
|
|
141
|
+
/* @__PURE__ */ jsx2(View2, { style: [styles2.divider, { backgroundColor: dividerColor }] })
|
|
197
142
|
] });
|
|
198
143
|
}
|
|
199
|
-
function ColorPage({ section,
|
|
200
|
-
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;
|
|
201
146
|
const displayFor = previewValue ?? ((hex) => hex);
|
|
202
147
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
203
|
-
/* @__PURE__ */
|
|
204
|
-
/* @__PURE__ */
|
|
205
|
-
/* @__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 })
|
|
206
151
|
] }) }),
|
|
207
|
-
/* @__PURE__ */
|
|
152
|
+
/* @__PURE__ */ jsx2(View2, { style: styles2.swatches, children: swatches.map((swatch) => {
|
|
208
153
|
const selected = swatch.value.toLowerCase() === value.toLowerCase();
|
|
209
|
-
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;
|
|
210
157
|
const swatchDisplay = displayFor(swatch.value);
|
|
211
|
-
|
|
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);
|
|
212
161
|
}) })
|
|
213
162
|
] });
|
|
214
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
|
+
});
|
|
215
184
|
var styles2 = StyleSheet2.create({
|
|
216
185
|
anchor: {
|
|
217
186
|
position: "relative"
|
|
@@ -255,38 +224,31 @@ var styles2 = StyleSheet2.create({
|
|
|
255
224
|
colorRowText: {
|
|
256
225
|
flex: 1
|
|
257
226
|
},
|
|
258
|
-
// Separates
|
|
259
|
-
// action, not just another row in the same list. Tinted with the seat's own color
|
|
260
|
-
// 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.
|
|
261
231
|
divider: {
|
|
262
232
|
height: 1,
|
|
263
233
|
marginVertical: 4,
|
|
264
234
|
opacity: 0.25
|
|
265
235
|
},
|
|
266
|
-
//
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
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: {
|
|
270
246
|
alignItems: "center",
|
|
271
247
|
borderRadius: 11,
|
|
272
248
|
height: 22,
|
|
273
249
|
justifyContent: "center",
|
|
274
250
|
width: 22
|
|
275
251
|
},
|
|
276
|
-
manageLabel: {
|
|
277
|
-
fontSize: 13,
|
|
278
|
-
fontWeight: "700",
|
|
279
|
-
letterSpacing: 0.5
|
|
280
|
-
},
|
|
281
|
-
// Centered rather than left-aligned like a normal row - see this row's own render-site comment
|
|
282
|
-
// for why (a footer action, not another selectable identity).
|
|
283
|
-
manageRowInner: {
|
|
284
|
-
alignItems: "center",
|
|
285
|
-
flexDirection: "row",
|
|
286
|
-
gap: 6,
|
|
287
|
-
height: "100%",
|
|
288
|
-
justifyContent: "center"
|
|
289
|
-
},
|
|
290
252
|
menu: {
|
|
291
253
|
borderRadius: 12,
|
|
292
254
|
borderWidth: MENU_BORDER_WIDTH,
|
|
@@ -302,29 +264,13 @@ var styles2 = StyleSheet2.create({
|
|
|
302
264
|
menuContent: {
|
|
303
265
|
padding: LIST_PADDING
|
|
304
266
|
},
|
|
305
|
-
//
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
height: 8,
|
|
309
|
-
width: 8
|
|
267
|
+
// With a footer pinned below, its own padding takes the bottom edge (same total height as before).
|
|
268
|
+
menuContentAboveFooter: {
|
|
269
|
+
paddingBottom: 0
|
|
310
270
|
},
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
},
|
|
315
|
-
rowDisabled: {
|
|
316
|
-
opacity: 0.35
|
|
317
|
-
},
|
|
318
|
-
rowInner: {
|
|
319
|
-
alignItems: "center",
|
|
320
|
-
flexDirection: "row",
|
|
321
|
-
flex: 1,
|
|
322
|
-
gap: 8,
|
|
323
|
-
paddingHorizontal: ROW_INSET
|
|
324
|
-
},
|
|
325
|
-
rowLabel: {
|
|
326
|
-
flex: 1,
|
|
327
|
-
fontSize: 14
|
|
271
|
+
menuFooter: {
|
|
272
|
+
paddingBottom: LIST_PADDING,
|
|
273
|
+
paddingHorizontal: LIST_PADDING
|
|
328
274
|
},
|
|
329
275
|
swatch: {
|
|
330
276
|
alignItems: "center",
|
|
@@ -337,6 +283,9 @@ var styles2 = StyleSheet2.create({
|
|
|
337
283
|
borderColor: "#ffffff",
|
|
338
284
|
borderWidth: 2
|
|
339
285
|
},
|
|
286
|
+
swatchTaken: {
|
|
287
|
+
opacity: 0.35
|
|
288
|
+
},
|
|
340
289
|
swatches: {
|
|
341
290
|
columnGap: GRID_GAP,
|
|
342
291
|
flexDirection: "row",
|
|
@@ -363,15 +312,128 @@ var styles2 = StyleSheet2.create({
|
|
|
363
312
|
}
|
|
364
313
|
});
|
|
365
314
|
|
|
366
|
-
// src/
|
|
367
|
-
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";
|
|
368
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";
|
|
369
431
|
import { useFocusChain } from "@rific/focus-chain";
|
|
370
432
|
import { useToast } from "@rific/toaster";
|
|
371
433
|
import { ConfirmDialog, getInlineColorPickerContentSize, InlineColorPicker, usePopoverHost } from "@tastic/hud";
|
|
372
434
|
import { useCallback, useEffect, useImperativeHandle, useMemo as useMemo2, useRef, useState as useState2 } from "react";
|
|
373
|
-
import { KeyboardAvoidingView, Platform,
|
|
374
|
-
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";
|
|
375
437
|
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
|
376
438
|
|
|
377
439
|
// src/profilesValidation.ts
|
|
@@ -407,7 +469,7 @@ function isValidProfile(value) {
|
|
|
407
469
|
}
|
|
408
470
|
|
|
409
471
|
// src/ProfilesManager.tsx
|
|
410
|
-
import { Fragment as Fragment2, jsx as
|
|
472
|
+
import { Fragment as Fragment2, jsx as jsx7, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
411
473
|
var CHIP_SIZE2 = 40;
|
|
412
474
|
function deriveTag(name) {
|
|
413
475
|
const trimmed = name.trim();
|
|
@@ -484,38 +546,38 @@ function ProfilesManager({ profiles, defaultColor, onCreate, onSave, onDelete, h
|
|
|
484
546
|
}, [confirmDeleteId, editingId, onDelete]);
|
|
485
547
|
const sortedProfiles = useMemo2(() => [...profiles].sort((a, b) => a.name.localeCompare(b.name)), [profiles]);
|
|
486
548
|
const rows = [...sortedProfiles.map((profile) => ({ kind: "profile", profile })), { kind: "new" }];
|
|
487
|
-
return /* @__PURE__ */
|
|
488
|
-
/* @__PURE__ */
|
|
549
|
+
return /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
550
|
+
/* @__PURE__ */ jsxs3(View4, { style: [styles4.header, { paddingTop: 8 + insets.top, paddingLeft: 8 + insets.left }], children: [
|
|
489
551
|
headerLeft,
|
|
490
|
-
/* @__PURE__ */
|
|
552
|
+
/* @__PURE__ */ jsx7(Text4, { variant: titleVariant, style: [styles4.title, { color: fg }], children: "Profiles" })
|
|
491
553
|
] }),
|
|
492
|
-
/* @__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) => {
|
|
493
555
|
if (row.kind === "new") {
|
|
494
556
|
if (editingId !== "new") {
|
|
495
|
-
return /* @__PURE__ */
|
|
496
|
-
/* @__PURE__ */
|
|
497
|
-
/* @__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" })
|
|
498
560
|
] }) }, "new");
|
|
499
561
|
}
|
|
500
|
-
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");
|
|
501
563
|
}
|
|
502
564
|
const { profile } = row;
|
|
503
565
|
if (editingId === profile.id) {
|
|
504
|
-
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);
|
|
505
567
|
}
|
|
506
|
-
return /* @__PURE__ */
|
|
507
|
-
/* @__PURE__ */
|
|
508
|
-
/* @__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 })
|
|
509
571
|
] }) }, profile.id);
|
|
510
572
|
}) }) }),
|
|
511
|
-
/* @__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) })
|
|
512
574
|
] });
|
|
513
575
|
}
|
|
514
576
|
function AlignedColorPicker({ useAlign, ...props }) {
|
|
515
577
|
const { width: windowWidth } = useWindowDimensions();
|
|
516
578
|
const { width, height } = getInlineColorPickerContentSize(defaultColors2.length, windowWidth);
|
|
517
579
|
const alignOverride = useAlign(props.host.openId === props.id, width, height);
|
|
518
|
-
return /* @__PURE__ */
|
|
580
|
+
return /* @__PURE__ */ jsx7(InlineColorPicker, { ...props, alignOverride });
|
|
519
581
|
}
|
|
520
582
|
function EditRow({ draftName, onNameChange, draftColor, onColorChange, draftTag, onTagChange, onSubmit, onDelete, autoFocus, fgMuted, host, dark, colorPreview, useColorPickerAlign }) {
|
|
521
583
|
const register = useFocusChain();
|
|
@@ -528,14 +590,14 @@ function EditRow({ draftName, onNameChange, draftColor, onColorChange, draftTag,
|
|
|
528
590
|
useEffect(() => {
|
|
529
591
|
if (host.openId === "color") tagFocusRef.current();
|
|
530
592
|
}, [host.openId]);
|
|
531
|
-
return /* @__PURE__ */
|
|
532
|
-
useColorPickerAlign ? /* @__PURE__ */
|
|
533
|
-
/* @__PURE__ */
|
|
534
|
-
/* @__PURE__ */
|
|
535
|
-
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 }) })
|
|
536
598
|
] });
|
|
537
599
|
}
|
|
538
|
-
var
|
|
600
|
+
var styles4 = StyleSheet4.create({
|
|
539
601
|
content: {
|
|
540
602
|
gap: 4,
|
|
541
603
|
paddingHorizontal: 20
|
|
@@ -617,8 +679,8 @@ var styles3 = StyleSheet3.create({
|
|
|
617
679
|
import { useAutoPaperTheme as useAutoPaperTheme2 } from "@rific/auto-paper";
|
|
618
680
|
import { IconButton } from "@rific/feedback-press";
|
|
619
681
|
import { useRef as useRef2 } from "react";
|
|
620
|
-
import { StyleSheet as
|
|
621
|
-
import { jsx as
|
|
682
|
+
import { StyleSheet as StyleSheet5, View as View5 } from "react-native";
|
|
683
|
+
import { jsx as jsx8 } from "react/jsx-runtime";
|
|
622
684
|
function ProfilesScreen({ profiles, defaultColor, onCreate, onSave, onDelete, onBack, fg: fgOverride, fgMuted, bg: bgOverride, titleVariant, colorPreview, useColorPickerAlign }) {
|
|
623
685
|
const { dark } = useAutoPaperTheme2();
|
|
624
686
|
const managerRef = useRef2(null);
|
|
@@ -628,9 +690,9 @@ function ProfilesScreen({ profiles, defaultColor, onCreate, onSave, onDelete, on
|
|
|
628
690
|
managerRef.current?.commitPendingEdit();
|
|
629
691
|
onBack();
|
|
630
692
|
};
|
|
631
|
-
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" }) }) });
|
|
632
694
|
}
|
|
633
|
-
var
|
|
695
|
+
var styles5 = StyleSheet5.create({
|
|
634
696
|
container: {
|
|
635
697
|
flex: 1
|
|
636
698
|
}
|
|
@@ -794,21 +856,52 @@ async function resolveInitialProfiles(groupId, localFallback) {
|
|
|
794
856
|
|
|
795
857
|
// src/redux/seatColorsSlice.ts
|
|
796
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
|
+
}
|
|
797
866
|
function createSeatColorsSlice(namespace, defaultState, mountKey = "seatColors") {
|
|
798
867
|
const setLastCpuColor = createActionCreator(`seatColors/${namespace}/setLastCpuColor`);
|
|
799
868
|
const setLastGuestColor = createActionCreator(`seatColors/${namespace}/setLastGuestColor`);
|
|
800
|
-
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
|
+
}
|
|
801
876
|
function reducer(state = defaultState, action) {
|
|
802
877
|
if (action.type === REHYDRATE2) {
|
|
803
878
|
const persisted = action.payload?.[mountKey];
|
|
804
|
-
|
|
879
|
+
const next = { ...defaultState, ...state, ...persisted };
|
|
880
|
+
delete next.profileOverride;
|
|
881
|
+
return next;
|
|
805
882
|
}
|
|
806
883
|
if (setLastCpuColor.match(action)) return { ...state, lastCpuColor: action.payload };
|
|
807
884
|
if (setLastGuestColor.match(action)) return { ...state, lastGuestColor: { ...state.lastGuestColor, [action.payload.seat]: action.payload.color } };
|
|
808
|
-
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
|
+
}
|
|
809
902
|
return state;
|
|
810
903
|
}
|
|
811
|
-
return { actions: { setLastCpuColor, setLastGuestColor,
|
|
904
|
+
return { actions: { setLastCpuColor, setLastGuestColor, setProfileColor }, reducer };
|
|
812
905
|
}
|
|
813
906
|
|
|
814
907
|
// src/redux/useSharedProfilesSync.ts
|
|
@@ -857,6 +950,7 @@ function avoidSeatColorClash(p1Color, p2Color, defaults) {
|
|
|
857
950
|
export {
|
|
858
951
|
MAX_PROFILE_NAME_LENGTH,
|
|
859
952
|
MAX_TAG_LENGTH,
|
|
953
|
+
OptionPicker,
|
|
860
954
|
ProfileChip,
|
|
861
955
|
ProfileColorProvider,
|
|
862
956
|
ProfilePicker,
|
|
@@ -867,11 +961,13 @@ export {
|
|
|
867
961
|
createProfileRecord,
|
|
868
962
|
createProfileSelectionSlice,
|
|
869
963
|
createSeatColorsSlice,
|
|
964
|
+
getOptionPickerContentSize,
|
|
870
965
|
getProfilePickerContentSize,
|
|
871
966
|
isSharedProfileStoreAvailable,
|
|
872
967
|
isValidProfile,
|
|
873
968
|
isValidTag,
|
|
874
969
|
loadSharedProfiles,
|
|
970
|
+
profileSeatColor,
|
|
875
971
|
profilesActions,
|
|
876
972
|
profilesReducer,
|
|
877
973
|
readSharedProfiles,
|