Refactor: Update Tenant PWA headers and tabs to use Playfair Display and Tamagui components
Some checks failed
linter / quality (push) Has been cancelled
tests / ci (push) Has been cancelled
tests / ui (push) Has been cancelled

This commit is contained in:
Codex Agent
2026-01-22 13:29:56 +01:00
parent b9d91c8f40
commit 911880f1a0
14 changed files with 425778 additions and 426862 deletions

View File

@@ -148,867 +148,6 @@ var tokens = {
size size
}; };
// node_modules/@tamagui/create-theme/dist/esm/isMinusZero.mjs
function isMinusZero(value) {
return 1 / value === Number.NEGATIVE_INFINITY;
}
__name(isMinusZero, "isMinusZero");
// node_modules/@tamagui/create-theme/dist/esm/themeInfo.mjs
var THEME_INFO = /* @__PURE__ */ new Map();
var getThemeInfo = /* @__PURE__ */ __name((theme, name) => THEME_INFO.get(name || JSON.stringify(theme)), "getThemeInfo");
var setThemeInfo = /* @__PURE__ */ __name((theme, info) => {
const next = {
...info,
cache: /* @__PURE__ */ new Map()
};
THEME_INFO.set(info.name || JSON.stringify(theme), next), THEME_INFO.set(JSON.stringify(info.definition), next);
}, "setThemeInfo");
// node_modules/@tamagui/create-theme/dist/esm/createTheme.mjs
var identityCache = /* @__PURE__ */ new Map();
function createTheme(palette, definition, options, name, skipCache = false) {
const cacheKey = skipCache ? "" : JSON.stringify([name, palette, definition, options]);
if (!skipCache && identityCache.has(cacheKey)) return identityCache.get(cacheKey);
const theme = {
...Object.fromEntries(Object.entries(definition).map(([key, offset]) => [key, getValue(palette, offset)])),
...options?.nonInheritedValues
};
return setThemeInfo(theme, {
palette,
definition,
options,
name
}), cacheKey && identityCache.set(cacheKey, theme), theme;
}
__name(createTheme, "createTheme");
var getValue = /* @__PURE__ */ __name((palette, value) => {
if (!palette) throw new Error("No palette!");
if (typeof value == "string") return value;
const max = palette.length - 1, next = (value === 0 ? !isMinusZero(value) : value >= 0) ? value : max + value, index = Math.min(Math.max(0, next), max);
return palette[index];
}, "getValue");
// node_modules/@tamagui/create-theme/dist/esm/helpers.mjs
function objectEntries(obj) {
return Object.entries(obj);
}
__name(objectEntries, "objectEntries");
function objectFromEntries(arr) {
return Object.fromEntries(arr);
}
__name(objectFromEntries, "objectFromEntries");
// node_modules/@tamagui/create-theme/dist/esm/masks.mjs
var createMask = /* @__PURE__ */ __name((createMask2) => typeof createMask2 == "function" ? {
name: createMask2.name || "unnamed",
mask: createMask2
} : createMask2, "createMask");
var skipMask = {
name: "skip-mask",
mask: /* @__PURE__ */ __name((template, opts) => {
const {
skip
} = opts;
return Object.fromEntries(Object.entries(template).filter(([k]) => !skip || !(k in skip)).map(([k, v]) => [k, applyOverrides(k, v, opts)]));
}, "mask")
};
function applyOverrides(key, value, opts) {
let override, strategy = opts.overrideStrategy;
const overrideSwap = opts.overrideSwap?.[key];
if (typeof overrideSwap < "u") override = overrideSwap, strategy = "swap";
else {
const overrideShift = opts.overrideShift?.[key];
if (typeof overrideShift < "u") override = overrideShift, strategy = "shift";
else {
const overrideDefault = opts.override?.[key];
typeof overrideDefault < "u" && (override = overrideDefault, strategy = opts.overrideStrategy);
}
}
return typeof override > "u" || typeof override == "string" ? value : strategy === "swap" ? override : value;
}
__name(applyOverrides, "applyOverrides");
var createIdentityMask = /* @__PURE__ */ __name(() => ({
name: "identity-mask",
mask: /* @__PURE__ */ __name((template, opts) => skipMask.mask(template, opts), "mask")
}), "createIdentityMask");
var createInverseMask = /* @__PURE__ */ __name(() => ({
name: "inverse-mask",
mask: /* @__PURE__ */ __name((template, opts) => {
const inversed = objectFromEntries(objectEntries(template).map(([k, v]) => [k, -v]));
return skipMask.mask(inversed, opts);
}, "mask")
}), "createInverseMask");
var createShiftMask = /* @__PURE__ */ __name(({
inverse
} = {}, defaultOptions) => ({
name: "shift-mask",
mask: /* @__PURE__ */ __name((template, opts) => {
const {
override,
overrideStrategy = "shift",
max: maxIn,
palette,
min = 0,
strength = 1
} = {
...defaultOptions,
...opts
}, values = Object.entries(template), max = maxIn ?? (palette ? Object.values(palette).length - 1 : Number.POSITIVE_INFINITY), out = {};
for (const [key, value] of values) {
if (typeof value == "string") continue;
if (typeof override?.[key] == "number") {
const overrideVal = override[key];
out[key] = overrideStrategy === "shift" ? value + overrideVal : overrideVal;
continue;
}
if (typeof override?.[key] == "string") {
out[key] = override[key];
continue;
}
const isPositive = value === 0 ? !isMinusZero(value) : value >= 0, direction = isPositive ? 1 : -1, invert = inverse ? -1 : 1, next = value + strength * direction * invert, clamped = isPositive ? Math.max(min, Math.min(max, next)) : Math.min(-min, Math.max(-max, next));
out[key] = clamped;
}
return skipMask.mask(out, opts);
}, "mask")
}), "createShiftMask");
var createWeakenMask = /* @__PURE__ */ __name((defaultOptions) => ({
name: "soften-mask",
mask: createShiftMask({}, defaultOptions).mask
}), "createWeakenMask");
var createSoftenMask = createWeakenMask;
var createStrengthenMask = /* @__PURE__ */ __name((defaultOptions) => ({
name: "strengthen-mask",
mask: createShiftMask({
inverse: true
}, defaultOptions).mask
}), "createStrengthenMask");
// node_modules/@tamagui/create-theme/dist/esm/applyMask.mjs
function applyMaskStateless(info, mask, options = {}, parentName) {
const skip = {
...options.skip
};
if (info.options?.nonInheritedValues) for (const key in info.options.nonInheritedValues) skip[key] = 1;
const maskOptions = {
parentName,
palette: info.palette,
...options,
skip
}, template = mask.mask(info.definition, maskOptions), theme = createTheme(info.palette, template);
return {
...info,
cache: /* @__PURE__ */ new Map(),
definition: template,
theme
};
}
__name(applyMaskStateless, "applyMaskStateless");
// node_modules/@tamagui/create-theme/dist/esm/combineMasks.mjs
var combineMasks = /* @__PURE__ */ __name((...masks2) => ({
name: "combine-mask",
mask: /* @__PURE__ */ __name((template, opts) => {
let current = getThemeInfo(template, opts.parentName), theme;
for (const mask2 of masks2) {
if (!current) throw new Error(`Nothing returned from mask: ${current}, for template: ${template} and mask: ${mask2.toString()}, given opts ${JSON.stringify(opts, null, 2)}`);
const next = applyMaskStateless(current, mask2, opts);
current = next, theme = next.theme;
}
return theme;
}, "mask")
}), "combineMasks");
// node_modules/color2k/dist/index.exports.import.es.mjs
function guard(low, high, value) {
return Math.min(Math.max(low, value), high);
}
__name(guard, "guard");
var ColorError = class extends Error {
static {
__name(this, "ColorError");
}
constructor(color2) {
super(`Failed to parse color: "${color2}"`);
}
};
var ColorError$1 = ColorError;
function parseToRgba(color2) {
if (typeof color2 !== "string") throw new ColorError$1(color2);
if (color2.trim().toLowerCase() === "transparent") return [0, 0, 0, 0];
let normalizedColor = color2.trim();
normalizedColor = namedColorRegex.test(color2) ? nameToHex(color2) : color2;
const reducedHexMatch = reducedHexRegex.exec(normalizedColor);
if (reducedHexMatch) {
const arr = Array.from(reducedHexMatch).slice(1);
return [...arr.slice(0, 3).map((x) => parseInt(r(x, 2), 16)), parseInt(r(arr[3] || "f", 2), 16) / 255];
}
const hexMatch = hexRegex.exec(normalizedColor);
if (hexMatch) {
const arr = Array.from(hexMatch).slice(1);
return [...arr.slice(0, 3).map((x) => parseInt(x, 16)), parseInt(arr[3] || "ff", 16) / 255];
}
const rgbaMatch = rgbaRegex.exec(normalizedColor);
if (rgbaMatch) {
const arr = Array.from(rgbaMatch).slice(1);
return [...arr.slice(0, 3).map((x) => parseInt(x, 10)), parseFloat(arr[3] || "1")];
}
const hslaMatch = hslaRegex.exec(normalizedColor);
if (hslaMatch) {
const [h, s, l, a] = Array.from(hslaMatch).slice(1).map(parseFloat);
if (guard(0, 100, s) !== s) throw new ColorError$1(color2);
if (guard(0, 100, l) !== l) throw new ColorError$1(color2);
return [...hslToRgb(h, s, l), Number.isNaN(a) ? 1 : a];
}
throw new ColorError$1(color2);
}
__name(parseToRgba, "parseToRgba");
function hash(str) {
let hash2 = 5381;
let i = str.length;
while (i) {
hash2 = hash2 * 33 ^ str.charCodeAt(--i);
}
return (hash2 >>> 0) % 2341;
}
__name(hash, "hash");
var colorToInt = /* @__PURE__ */ __name((x) => parseInt(x.replace(/_/g, ""), 36), "colorToInt");
var compressedColorMap = "1q29ehhb 1n09sgk7 1kl1ekf_ _yl4zsno 16z9eiv3 1p29lhp8 _bd9zg04 17u0____ _iw9zhe5 _to73___ _r45e31e _7l6g016 _jh8ouiv _zn3qba8 1jy4zshs 11u87k0u 1ro9yvyo 1aj3xael 1gz9zjz0 _3w8l4xo 1bf1ekf_ _ke3v___ _4rrkb__ 13j776yz _646mbhl _nrjr4__ _le6mbhl 1n37ehkb _m75f91n _qj3bzfz 1939yygw 11i5z6x8 _1k5f8xs 1509441m 15t5lwgf _ae2th1n _tg1ugcv 1lp1ugcv 16e14up_ _h55rw7n _ny9yavn _7a11xb_ 1ih442g9 _pv442g9 1mv16xof 14e6y7tu 1oo9zkds 17d1cisi _4v9y70f _y98m8kc 1019pq0v 12o9zda8 _348j4f4 1et50i2o _8epa8__ _ts6senj 1o350i2o 1mi9eiuo 1259yrp0 1ln80gnw _632xcoy 1cn9zldc _f29edu4 1n490c8q _9f9ziet 1b94vk74 _m49zkct 1kz6s73a 1eu9dtog _q58s1rz 1dy9sjiq __u89jo3 _aj5nkwg _ld89jo3 13h9z6wx _qa9z2ii _l119xgq _bs5arju 1hj4nwk9 1qt4nwk9 1ge6wau6 14j9zlcw 11p1edc_ _ms1zcxe _439shk6 _jt9y70f _754zsow 1la40eju _oq5p___ _x279qkz 1fa5r3rv _yd2d9ip _424tcku _8y1di2_ _zi2uabw _yy7rn9h 12yz980_ __39ljp6 1b59zg0x _n39zfzp 1fy9zest _b33k___ _hp9wq92 1il50hz4 _io472ub _lj9z3eo 19z9ykg0 _8t8iu3a 12b9bl4a 1ak5yw0o _896v4ku _tb8k8lv _s59zi6t _c09ze0p 1lg80oqn 1id9z8wb _238nba5 1kq6wgdi _154zssg _tn3zk49 _da9y6tc 1sg7cv4f _r12jvtt 1gq5fmkz 1cs9rvci _lp9jn1c _xw1tdnb 13f9zje6 16f6973h _vo7ir40 _bt5arjf _rc45e4t _hr4e100 10v4e100 _hc9zke2 _w91egv_ _sj2r1kk 13c87yx8 _vqpds__ _ni8ggk8 _tj9yqfb 1ia2j4r4 _7x9b10u 1fc9ld4j 1eq9zldr _5j9lhpx _ez9zl6o _md61fzm".split(" ").reduce((acc, next) => {
const key = colorToInt(next.substring(0, 3));
const hex = colorToInt(next.substring(3)).toString(16);
let prefix = "";
for (let i = 0; i < 6 - hex.length; i++) {
prefix += "0";
}
acc[key] = `${prefix}${hex}`;
return acc;
}, {});
function nameToHex(color2) {
const normalizedColorName = color2.toLowerCase().trim();
const result = compressedColorMap[hash(normalizedColorName)];
if (!result) throw new ColorError$1(color2);
return `#${result}`;
}
__name(nameToHex, "nameToHex");
var r = /* @__PURE__ */ __name((str, amount) => Array.from(Array(amount)).map(() => str).join(""), "r");
var reducedHexRegex = new RegExp(`^#${r("([a-f0-9])", 3)}([a-f0-9])?$`, "i");
var hexRegex = new RegExp(`^#${r("([a-f0-9]{2})", 3)}([a-f0-9]{2})?$`, "i");
var rgbaRegex = new RegExp(`^rgba?\\(\\s*(\\d+)\\s*${r(",\\s*(\\d+)\\s*", 2)}(?:,\\s*([\\d.]+))?\\s*\\)$`, "i");
var hslaRegex = /^hsla?\(\s*([\d.]+)\s*,\s*([\d.]+)%\s*,\s*([\d.]+)%(?:\s*,\s*([\d.]+))?\s*\)$/i;
var namedColorRegex = /^[a-z]+$/i;
var roundColor = /* @__PURE__ */ __name((color2) => {
return Math.round(color2 * 255);
}, "roundColor");
var hslToRgb = /* @__PURE__ */ __name((hue, saturation, lightness) => {
let l = lightness / 100;
if (saturation === 0) {
return [l, l, l].map(roundColor);
}
const huePrime = (hue % 360 + 360) % 360 / 60;
const chroma = (1 - Math.abs(2 * l - 1)) * (saturation / 100);
const secondComponent = chroma * (1 - Math.abs(huePrime % 2 - 1));
let red3 = 0;
let green3 = 0;
let blue3 = 0;
if (huePrime >= 0 && huePrime < 1) {
red3 = chroma;
green3 = secondComponent;
} else if (huePrime >= 1 && huePrime < 2) {
red3 = secondComponent;
green3 = chroma;
} else if (huePrime >= 2 && huePrime < 3) {
green3 = chroma;
blue3 = secondComponent;
} else if (huePrime >= 3 && huePrime < 4) {
green3 = secondComponent;
blue3 = chroma;
} else if (huePrime >= 4 && huePrime < 5) {
red3 = secondComponent;
blue3 = chroma;
} else if (huePrime >= 5 && huePrime < 6) {
red3 = chroma;
blue3 = secondComponent;
}
const lightnessModification = l - chroma / 2;
const finalRed = red3 + lightnessModification;
const finalGreen = green3 + lightnessModification;
const finalBlue = blue3 + lightnessModification;
return [finalRed, finalGreen, finalBlue].map(roundColor);
}, "hslToRgb");
function parseToHsla(color2) {
const [red3, green3, blue3, alpha] = parseToRgba(color2).map((value, index) => (
// 3rd index is alpha channel which is already normalized
index === 3 ? value : value / 255
));
const max = Math.max(red3, green3, blue3);
const min = Math.min(red3, green3, blue3);
const lightness = (max + min) / 2;
if (max === min) return [0, 0, lightness, alpha];
const delta = max - min;
const saturation = lightness > 0.5 ? delta / (2 - max - min) : delta / (max + min);
const hue = 60 * (red3 === max ? (green3 - blue3) / delta + (green3 < blue3 ? 6 : 0) : green3 === max ? (blue3 - red3) / delta + 2 : (red3 - green3) / delta + 4);
return [hue, saturation, lightness, alpha];
}
__name(parseToHsla, "parseToHsla");
function hsla(hue, saturation, lightness, alpha) {
return `hsla(${(hue % 360).toFixed()}, ${guard(0, 100, saturation * 100).toFixed()}%, ${guard(0, 100, lightness * 100).toFixed()}%, ${parseFloat(guard(0, 1, alpha).toFixed(3))})`;
}
__name(hsla, "hsla");
// node_modules/@tamagui/theme-builder/dist/esm/helpers.mjs
var objectKeys = /* @__PURE__ */ __name((obj) => Object.keys(obj), "objectKeys");
function objectFromEntries2(arr) {
return Object.fromEntries(arr);
}
__name(objectFromEntries2, "objectFromEntries");
// node_modules/@tamagui/theme-builder/dist/esm/defaultTemplates.mjs
var getTemplates = /* @__PURE__ */ __name(() => {
const lightTemplates = getBaseTemplates("light"), darkTemplates = getBaseTemplates("dark");
return {
...objectFromEntries2(objectKeys(lightTemplates).map((name) => [`light_${name}`, lightTemplates[name]])),
...objectFromEntries2(objectKeys(darkTemplates).map((name) => [`dark_${name}`, darkTemplates[name]]))
};
}, "getTemplates");
var getBaseTemplates = /* @__PURE__ */ __name((scheme) => {
const isLight = scheme === "light", bgIndex = 6, lighten = isLight ? -1 : 1, darken = -lighten, borderColor = bgIndex + 3, baseColors = {
color: -bgIndex,
colorHover: -bgIndex - 1,
colorPress: -bgIndex,
colorFocus: -bgIndex - 1,
placeholderColor: -bgIndex - 3,
outlineColor: -2
}, base = {
accentBackground: 0,
accentColor: -0,
background0: 1,
background02: 2,
background04: 3,
background06: 4,
background08: 5,
color1: bgIndex,
color2: bgIndex + 1,
color3: bgIndex + 2,
color4: bgIndex + 3,
color5: bgIndex + 4,
color6: bgIndex + 5,
color7: bgIndex + 6,
color8: bgIndex + 7,
color9: bgIndex + 8,
color10: bgIndex + 9,
color11: bgIndex + 10,
color12: bgIndex + 11,
color0: -1,
color02: -2,
color04: -3,
color06: -4,
color08: -5,
// the background, color, etc keys here work like generics - they make it so you
// can publish components for others to use without mandating a specific color scale
// the @tamagui/button Button component looks for `$background`, so you set the
// dark_red_Button theme to have a stronger background than the dark_red theme.
background: bgIndex,
backgroundHover: bgIndex + lighten,
// always lighten on hover no matter the scheme
backgroundPress: bgIndex + darken,
// always darken on press no matter the theme
backgroundFocus: bgIndex + darken,
borderColor,
borderColorHover: borderColor + lighten,
borderColorPress: borderColor + darken,
borderColorFocus: borderColor,
...baseColors,
colorTransparent: -1
}, surface1 = {
...baseColors,
background: base.background + 1,
backgroundHover: base.backgroundHover + 1,
backgroundPress: base.backgroundPress + 1,
backgroundFocus: base.backgroundFocus + 1,
borderColor: base.borderColor + 1,
borderColorHover: base.borderColorHover + 1,
borderColorFocus: base.borderColorFocus + 1,
borderColorPress: base.borderColorPress + 1
}, surface2 = {
...baseColors,
background: base.background + 2,
backgroundHover: base.backgroundHover + 2,
backgroundPress: base.backgroundPress + 2,
backgroundFocus: base.backgroundFocus + 2,
borderColor: base.borderColor + 2,
borderColorHover: base.borderColorHover + 2,
borderColorFocus: base.borderColorFocus + 2,
borderColorPress: base.borderColorPress + 2
}, surface3 = {
...baseColors,
background: base.background + 3,
backgroundHover: base.backgroundHover + 3,
backgroundPress: base.backgroundPress + 3,
backgroundFocus: base.backgroundFocus + 3,
borderColor: base.borderColor + 3,
borderColorHover: base.borderColorHover + 3,
borderColorFocus: base.borderColorFocus + 3,
borderColorPress: base.borderColorPress + 3
}, alt1 = {
color: base.color - 1,
colorHover: base.colorHover - 1,
colorPress: base.colorPress - 1,
colorFocus: base.colorFocus - 1
}, alt2 = {
color: base.color - 2,
colorHover: base.colorHover - 2,
colorPress: base.colorPress - 2,
colorFocus: base.colorFocus - 2
}, inverse = Object.fromEntries(Object.entries(base).map(([key, index]) => [key, -index]));
return {
base,
surface1,
surface2,
surface3,
alt1,
alt2,
inverse
};
}, "getBaseTemplates");
var defaultTemplates = getTemplates();
// node_modules/@tamagui/theme-builder/dist/esm/getThemeSuitePalettes.mjs
var paletteSize = 12;
var generateColorPalette = /* @__PURE__ */ __name(({
palette: buildPalette,
scheme
}) => {
if (!buildPalette) return [];
const {
anchors
} = buildPalette;
let palette = [];
const add = /* @__PURE__ */ __name((h, s, l, a) => {
palette.push(hsla(h, s, l, a ?? 1));
}, "add"), numAnchors = Object.keys(anchors).length;
for (const [anchorIndex, anchor] of anchors.entries()) {
const [h, s, l, a] = [anchor.hue[scheme], anchor.sat[scheme], anchor.lum[scheme], anchor.alpha?.[scheme] ?? 1];
if (anchorIndex !== 0) {
const lastAnchor = anchors[anchorIndex - 1], steps = anchor.index - lastAnchor.index, lastHue = lastAnchor.hue[scheme], lastSat = lastAnchor.sat[scheme], lastLum = lastAnchor.lum[scheme], stepHue = (lastHue - h) / steps, stepSat = (lastSat - s) / steps, stepLum = (lastLum - l) / steps;
for (let step = lastAnchor.index + 1; step < anchor.index; step++) {
const str = anchor.index - step;
add(h + stepHue * str, s + stepSat * str, l + stepLum * str);
}
}
if (add(h, s, l, a), anchorIndex === numAnchors - 1 && palette.length < paletteSize) for (let step = anchor.index + 1; step < paletteSize; step++) add(h, s, l);
}
const background = palette[0], foreground = palette[palette.length - 1], transparentValues = [background, foreground].map((color2) => {
const [h, s, l] = parseToHsla(color2);
return [hsla(h, s, l, 0), hsla(h, s, l, 0.2), hsla(h, s, l, 0.4), hsla(h, s, l, 0.6), hsla(h, s, l, 0.8)];
}), reverseForeground = [...transparentValues[1]].reverse();
return palette = [...transparentValues[0], ...palette, ...reverseForeground], palette;
}, "generateColorPalette");
function getThemeSuitePalettes(palette) {
return {
light: generateColorPalette({
palette,
scheme: "light"
}),
dark: generateColorPalette({
palette,
scheme: "dark"
})
};
}
__name(getThemeSuitePalettes, "getThemeSuitePalettes");
// node_modules/@tamagui/theme-builder/dist/esm/createThemes.mjs
var defaultPalettes = createPalettes(getThemesPalettes({
base: {
palette: ["#fff", "#000"]
},
accent: {
palette: ["#ff0000", "#ff9999"]
}
}));
function getSchemePalette(colors3) {
return {
light: colors3,
dark: [...colors3].reverse()
};
}
__name(getSchemePalette, "getSchemePalette");
function getAnchors(palette) {
const numItems = palette.light.length;
return palette.light.map((lcolor, index) => {
const dcolor = palette.dark[index], [lhue, lsat, llum, lalpha] = parseToHsla(lcolor), [dhue, dsat, dlum, dalpha] = parseToHsla(dcolor);
return {
index: spreadIndex(11, numItems, index),
hue: {
light: lhue,
dark: dhue
},
sat: {
light: lsat,
dark: dsat
},
lum: {
light: llum,
dark: dlum
},
alpha: {
light: lalpha,
dark: dalpha
}
};
});
}
__name(getAnchors, "getAnchors");
function spreadIndex(maxIndex, numItems, index) {
return Math.round(index / (numItems - 1) * maxIndex);
}
__name(spreadIndex, "spreadIndex");
function coerceSimplePaletteToSchemePalette(def) {
return Array.isArray(def) ? getSchemePalette(def) : def;
}
__name(coerceSimplePaletteToSchemePalette, "coerceSimplePaletteToSchemePalette");
function getThemesPalettes(props) {
const base = coerceSimplePaletteToSchemePalette(props.base.palette), accent = props.accent ? coerceSimplePaletteToSchemePalette(props.accent.palette) : null, baseAnchors = getAnchors(base);
function getSubThemesPalettes(defs) {
return Object.fromEntries(Object.entries(defs).map(([key, value]) => [key, {
name: key,
anchors: value.palette ? getAnchors(coerceSimplePaletteToSchemePalette(value.palette)) : baseAnchors
}]));
}
__name(getSubThemesPalettes, "getSubThemesPalettes");
return {
base: {
name: "base",
anchors: baseAnchors
},
...accent && {
accent: {
name: "accent",
anchors: getAnchors(accent)
}
},
...props.childrenThemes && getSubThemesPalettes(props.childrenThemes),
...props.grandChildrenThemes && getSubThemesPalettes(props.grandChildrenThemes)
};
}
__name(getThemesPalettes, "getThemesPalettes");
function createPalettes(palettes) {
const accentPalettes = palettes.accent ? getThemeSuitePalettes(palettes.accent) : null, basePalettes = getThemeSuitePalettes(palettes.base);
return Object.fromEntries(Object.entries(palettes).flatMap(([name, palette]) => {
const palettes2 = getThemeSuitePalettes(palette), oppositePalettes = name.startsWith("accent") ? basePalettes : accentPalettes || basePalettes;
if (!oppositePalettes) return [];
const oppositeLight = oppositePalettes.light, oppositeDark = oppositePalettes.dark, bgOffset = 7;
return [[name === "base" ? "light" : `light_${name}`, [oppositeLight[bgOffset], ...palettes2.light, oppositeLight[oppositeLight.length - bgOffset - 1]]], [name === "base" ? "dark" : `dark_${name}`, [oppositeDark[oppositeDark.length - bgOffset - 1], ...palettes2.dark, oppositeDark[bgOffset]]]];
}));
}
__name(createPalettes, "createPalettes");
// node_modules/@tamagui/theme-builder/dist/esm/defaultTemplatesStronger.mjs
var getTemplates2 = /* @__PURE__ */ __name(() => {
const lightTemplates = getBaseTemplates2("light"), darkTemplates = getBaseTemplates2("dark");
return {
...objectFromEntries2(objectKeys(lightTemplates).map((name) => [`light_${name}`, lightTemplates[name]])),
...objectFromEntries2(objectKeys(darkTemplates).map((name) => [`dark_${name}`, darkTemplates[name]]))
};
}, "getTemplates");
var getBaseTemplates2 = /* @__PURE__ */ __name((scheme) => {
const isLight = scheme === "light", bgIndex = 6, lighten = isLight ? -1 : 1, darken = -lighten, borderColor = bgIndex + 3, baseColors = {
color: -bgIndex,
colorHover: -bgIndex - 1,
colorPress: -bgIndex,
colorFocus: -bgIndex - 1,
placeholderColor: -bgIndex - 3,
outlineColor: -2
}, base = {
accentBackground: 0,
accentColor: -0,
background0: 1,
background02: 2,
background04: 3,
background06: 4,
background08: 5,
color1: bgIndex,
color2: bgIndex + 1,
color3: bgIndex + 2,
color4: bgIndex + 3,
color5: bgIndex + 4,
color6: bgIndex + 5,
color7: bgIndex + 6,
color8: bgIndex + 7,
color9: bgIndex + 8,
color10: bgIndex + 9,
color11: bgIndex + 10,
color12: bgIndex + 11,
color0: -1,
color02: -2,
color04: -3,
color06: -4,
color08: -5,
// the background, color, etc keys here work like generics - they make it so you
// can publish components for others to use without mandating a specific color scale
// the @tamagui/button Button component looks for `$background`, so you set the
// dark_red_Button theme to have a stronger background than the dark_red theme.
background: bgIndex,
backgroundHover: bgIndex + lighten,
// always lighten on hover no matter the scheme
backgroundPress: bgIndex + darken,
// always darken on press no matter the theme
backgroundFocus: bgIndex + darken,
borderColor,
borderColorHover: borderColor + lighten,
borderColorPress: borderColor + darken,
borderColorFocus: borderColor,
...baseColors,
colorTransparent: -1
}, surface1 = {
...baseColors,
background: base.background + 2,
backgroundHover: base.backgroundHover + 2,
backgroundPress: base.backgroundPress + 2,
backgroundFocus: base.backgroundFocus + 2,
borderColor: base.borderColor + 2,
borderColorHover: base.borderColorHover + 2,
borderColorFocus: base.borderColorFocus + 2,
borderColorPress: base.borderColorPress + 2
}, surface2 = {
...baseColors,
background: base.background + 3,
backgroundHover: base.backgroundHover + 3,
backgroundPress: base.backgroundPress + 3,
backgroundFocus: base.backgroundFocus + 3,
borderColor: base.borderColor + 3,
borderColorHover: base.borderColorHover + 3,
borderColorFocus: base.borderColorFocus + 3,
borderColorPress: base.borderColorPress + 3
}, surface3 = {
...baseColors,
background: base.background + 4,
backgroundHover: base.backgroundHover + 4,
backgroundPress: base.backgroundPress + 4,
backgroundFocus: base.backgroundFocus + 4,
borderColor: base.borderColor + 4,
borderColorHover: base.borderColorHover + 4,
borderColorFocus: base.borderColorFocus + 4,
borderColorPress: base.borderColorPress + 4
}, alt1 = {
color: base.color - 1,
colorHover: base.colorHover - 1,
colorPress: base.colorPress - 1,
colorFocus: base.colorFocus - 1
}, alt2 = {
color: base.color - 2,
colorHover: base.colorHover - 2,
colorPress: base.colorPress - 2,
colorFocus: base.colorFocus - 2
}, inverse = Object.fromEntries(Object.entries(base).map(([key, index]) => [key, -index]));
return {
base,
surface1,
surface2,
surface3,
alt1,
alt2,
inverse
};
}, "getBaseTemplates");
var defaultTemplatesStronger = getTemplates2();
// node_modules/@tamagui/theme-builder/dist/esm/defaultTemplatesStrongest.mjs
var getTemplates3 = /* @__PURE__ */ __name(() => {
const lightTemplates = getBaseTemplates3("light"), darkTemplates = getBaseTemplates3("dark");
return {
...objectFromEntries2(objectKeys(lightTemplates).map((name) => [`light_${name}`, lightTemplates[name]])),
...objectFromEntries2(objectKeys(darkTemplates).map((name) => [`dark_${name}`, darkTemplates[name]]))
};
}, "getTemplates");
var getBaseTemplates3 = /* @__PURE__ */ __name((scheme) => {
const isLight = scheme === "light", bgIndex = 6, lighten = isLight ? -1 : 1, darken = -lighten, borderColor = bgIndex + 3, baseColors = {
color: -bgIndex,
colorHover: -bgIndex - 1,
colorPress: -bgIndex,
colorFocus: -bgIndex - 1,
placeholderColor: -bgIndex - 3,
outlineColor: -2
}, base = {
accentBackground: 0,
accentColor: -0,
background0: 1,
background02: 2,
background04: 3,
background06: 4,
background08: 5,
color1: bgIndex,
color2: bgIndex + 1,
color3: bgIndex + 2,
color4: bgIndex + 3,
color5: bgIndex + 4,
color6: bgIndex + 5,
color7: bgIndex + 6,
color8: bgIndex + 7,
color9: bgIndex + 8,
color10: bgIndex + 9,
color11: bgIndex + 10,
color12: bgIndex + 11,
color0: -1,
color02: -2,
color04: -3,
color06: -4,
color08: -5,
// the background, color, etc keys here work like generics - they make it so you
// can publish components for others to use without mandating a specific color scale
// the @tamagui/button Button component looks for `$background`, so you set the
// dark_red_Button theme to have a stronger background than the dark_red theme.
background: bgIndex,
backgroundHover: bgIndex + lighten,
// always lighten on hover no matter the scheme
backgroundPress: bgIndex + darken,
// always darken on press no matter the theme
backgroundFocus: bgIndex + darken,
borderColor,
borderColorHover: borderColor + lighten,
borderColorPress: borderColor + darken,
borderColorFocus: borderColor,
...baseColors,
colorTransparent: -1
}, surface1 = {
...baseColors,
background: base.background + 3,
backgroundHover: base.backgroundHover + 3,
backgroundPress: base.backgroundPress + 3,
backgroundFocus: base.backgroundFocus + 3,
borderColor: base.borderColor + 3,
borderColorHover: base.borderColorHover + 3,
borderColorFocus: base.borderColorFocus + 3,
borderColorPress: base.borderColorPress + 3
}, surface2 = {
...baseColors,
background: base.background + 4,
backgroundHover: base.backgroundHover + 4,
backgroundPress: base.backgroundPress + 4,
backgroundFocus: base.backgroundFocus + 4,
borderColor: base.borderColor + 4,
borderColorHover: base.borderColorHover + 4,
borderColorFocus: base.borderColorFocus + 4,
borderColorPress: base.borderColorPress + 4
}, surface3 = {
...baseColors,
background: base.background + 5,
backgroundHover: base.backgroundHover + 5,
backgroundPress: base.backgroundPress + 5,
backgroundFocus: base.backgroundFocus + 5,
borderColor: base.borderColor + 5,
borderColorHover: base.borderColorHover + 5,
borderColorFocus: base.borderColorFocus + 5,
borderColorPress: base.borderColorPress + 5
}, alt1 = {
color: base.color - 1,
colorHover: base.colorHover - 1,
colorPress: base.colorPress - 1,
colorFocus: base.colorFocus - 1
}, alt2 = {
color: base.color - 2,
colorHover: base.colorHover - 2,
colorPress: base.colorPress - 2,
colorFocus: base.colorFocus - 2
}, inverse = Object.fromEntries(Object.entries(base).map(([key, index]) => [key, -index]));
return {
base,
surface1,
surface2,
surface3,
alt1,
alt2,
inverse
};
}, "getBaseTemplates");
var defaultTemplatesStrongest = getTemplates3();
// node_modules/@tamagui/theme-builder/dist/esm/masks.mjs
var masks = {
identity: createIdentityMask(),
soften: createSoftenMask(),
soften2: createSoftenMask({
strength: 2
}),
soften3: createSoftenMask({
strength: 3
}),
strengthen: createStrengthenMask(),
inverse: createInverseMask(),
inverseSoften: combineMasks(createInverseMask(), createSoftenMask({
strength: 2
})),
inverseSoften2: combineMasks(createInverseMask(), createSoftenMask({
strength: 3
})),
inverseSoften3: combineMasks(createInverseMask(), createSoftenMask({
strength: 4
})),
inverseStrengthen2: combineMasks(createInverseMask(), createStrengthenMask({
strength: 2
})),
strengthenButSoftenBorder: createMask((template, options) => {
const stronger = createStrengthenMask().mask(template, options), softer = createSoftenMask().mask(template, options);
return {
...stronger,
borderColor: softer.borderColor,
borderColorHover: softer.borderColorHover,
borderColorPress: softer.borderColorPress,
borderColorFocus: softer.borderColorFocus
};
}),
soften2Border1: createMask((template, options) => {
const softer2 = createSoftenMask({
strength: 2
}).mask(template, options), softer1 = createSoftenMask({
strength: 1
}).mask(template, options);
return {
...softer2,
borderColor: softer1.borderColor,
borderColorHover: softer1.borderColorHover,
borderColorPress: softer1.borderColorPress,
borderColorFocus: softer1.borderColorFocus
};
}),
soften3FlatBorder: createMask((template, options) => {
const borderMask = createSoftenMask({
strength: 2
}).mask(template, options);
return {
...createSoftenMask({
strength: 3
}).mask(template, options),
borderColor: borderMask.borderColor,
borderColorHover: borderMask.borderColorHover,
borderColorPress: borderMask.borderColorPress,
borderColorFocus: borderMask.borderColorFocus
};
}),
softenBorder: createMask((template, options) => {
const plain = skipMask.mask(template, options), softer = createSoftenMask().mask(template, options);
return {
...plain,
borderColor: softer.borderColor,
borderColorHover: softer.borderColorHover,
borderColorPress: softer.borderColorPress,
borderColorFocus: softer.borderColorFocus
};
}),
softenBorder2: createMask((template, options) => {
const plain = skipMask.mask(template, options), softer = createSoftenMask({
strength: 2
}).mask(template, options);
return {
...plain,
borderColor: softer.borderColor,
borderColorHover: softer.borderColorHover,
borderColorPress: softer.borderColorPress,
borderColorFocus: softer.borderColorFocus
};
})
};
// node_modules/@tamagui/themes/dist/esm/generated-v4.mjs // node_modules/@tamagui/themes/dist/esm/generated-v4.mjs
function t(a) { function t(a) {
let res = {}; let res = {};
@@ -4263,12 +3402,12 @@ var fonts2 = {
}, },
heading: { heading: {
...defaultConfig.fonts.heading, ...defaultConfig.fonts.heading,
family: "Archivo Black", family: "Playfair Display",
weight: sharedWeights weight: sharedWeights
}, },
display: { display: {
...defaultConfig.fonts.heading, ...defaultConfig.fonts.heading,
family: "Archivo Black", family: "Playfair Display",
weight: sharedWeights weight: sharedWeights
} }
}; };

File diff suppressed because it is too large Load Diff

View File

@@ -118,319 +118,8 @@ var isWindowDefined = typeof window < "u";
var isClient = isWeb && isWindowDefined; var isClient = isWeb && isWindowDefined;
var isChrome = typeof navigator < "u" && /Chrome/.test(navigator.userAgent || ""); var isChrome = typeof navigator < "u" && /Chrome/.test(navigator.userAgent || "");
var isWebTouchable = isClient && ("ontouchstart" in window || navigator.maxTouchPoints > 0); var isWebTouchable = isClient && ("ontouchstart" in window || navigator.maxTouchPoints > 0);
var isAndroid = false;
var isIos = process.env.TEST_NATIVE_PLATFORM === "ios"; var isIos = process.env.TEST_NATIVE_PLATFORM === "ios";
// node_modules/@tamagui/helpers/dist/esm/validStyleProps.mjs
var textColors = {
color: true,
textDecorationColor: true,
textShadowColor: true
};
var tokenCategories = {
radius: {
borderRadius: true,
borderTopLeftRadius: true,
borderTopRightRadius: true,
borderBottomLeftRadius: true,
borderBottomRightRadius: true,
// logical
borderStartStartRadius: true,
borderStartEndRadius: true,
borderEndStartRadius: true,
borderEndEndRadius: true
},
size: {
width: true,
height: true,
minWidth: true,
minHeight: true,
maxWidth: true,
maxHeight: true,
blockSize: true,
minBlockSize: true,
maxBlockSize: true,
inlineSize: true,
minInlineSize: true,
maxInlineSize: true
},
zIndex: {
zIndex: true
},
color: {
backgroundColor: true,
borderColor: true,
borderBlockStartColor: true,
borderBlockEndColor: true,
borderBlockColor: true,
borderBottomColor: true,
borderInlineColor: true,
borderInlineStartColor: true,
borderInlineEndColor: true,
borderTopColor: true,
borderLeftColor: true,
borderRightColor: true,
borderEndColor: true,
borderStartColor: true,
shadowColor: true,
...textColors,
outlineColor: true,
caretColor: true
}
};
var stylePropsUnitless = {
WebkitLineClamp: true,
animationIterationCount: true,
aspectRatio: true,
borderImageOutset: true,
borderImageSlice: true,
borderImageWidth: true,
columnCount: true,
flex: true,
flexGrow: true,
flexOrder: true,
flexPositive: true,
flexShrink: true,
flexNegative: true,
fontWeight: true,
gridRow: true,
gridRowEnd: true,
gridRowGap: true,
gridRowStart: true,
gridColumn: true,
gridColumnEnd: true,
gridColumnGap: true,
gridColumnStart: true,
gridTemplateColumns: true,
gridTemplateAreas: true,
lineClamp: true,
opacity: true,
order: true,
orphans: true,
tabSize: true,
widows: true,
zIndex: true,
zoom: true,
scale: true,
scaleX: true,
scaleY: true,
scaleZ: true,
shadowOpacity: true
};
var stylePropsTransform = {
x: true,
y: true,
scale: true,
perspective: true,
scaleX: true,
scaleY: true,
skewX: true,
skewY: true,
matrix: true,
rotate: true,
rotateY: true,
rotateX: true,
rotateZ: true
};
var stylePropsView = {
backfaceVisibility: true,
borderBottomEndRadius: true,
borderBottomStartRadius: true,
borderBottomWidth: true,
borderLeftWidth: true,
borderRightWidth: true,
borderBlockWidth: true,
borderBlockEndWidth: true,
borderBlockStartWidth: true,
borderInlineWidth: true,
borderInlineEndWidth: true,
borderInlineStartWidth: true,
borderStyle: true,
borderBlockStyle: true,
borderBlockEndStyle: true,
borderBlockStartStyle: true,
borderInlineStyle: true,
borderInlineEndStyle: true,
borderInlineStartStyle: true,
borderTopEndRadius: true,
borderTopStartRadius: true,
borderTopWidth: true,
borderWidth: true,
transform: true,
transformOrigin: true,
alignContent: true,
alignItems: true,
alignSelf: true,
borderEndWidth: true,
borderStartWidth: true,
bottom: true,
display: true,
end: true,
flexBasis: true,
flexDirection: true,
flexWrap: true,
gap: true,
columnGap: true,
rowGap: true,
justifyContent: true,
left: true,
margin: true,
marginBlock: true,
marginBlockEnd: true,
marginBlockStart: true,
marginInline: true,
marginInlineStart: true,
marginInlineEnd: true,
marginBottom: true,
marginEnd: true,
marginHorizontal: true,
marginLeft: true,
marginRight: true,
marginStart: true,
marginTop: true,
marginVertical: true,
overflow: true,
padding: true,
paddingBottom: true,
paddingInline: true,
paddingBlock: true,
paddingBlockStart: true,
paddingInlineEnd: true,
paddingInlineStart: true,
paddingEnd: true,
paddingHorizontal: true,
paddingLeft: true,
paddingRight: true,
paddingStart: true,
paddingTop: true,
paddingVertical: true,
position: true,
right: true,
start: true,
top: true,
inset: true,
insetBlock: true,
insetBlockEnd: true,
insetBlockStart: true,
insetInline: true,
insetInlineEnd: true,
insetInlineStart: true,
direction: true,
shadowOffset: true,
shadowRadius: true,
...tokenCategories.color,
...tokenCategories.radius,
...tokenCategories.size,
...tokenCategories.radius,
...stylePropsTransform,
...stylePropsUnitless,
boxShadow: true,
filter: true,
// RN 0.77+ style props (set REACT_NATIVE_PRE_77=1 for older RN)
...!process.env.REACT_NATIVE_PRE_77 && {
boxSizing: true,
mixBlendMode: true,
outlineColor: true,
outlineSpread: true,
outlineStyle: true,
outlineWidth: true
},
// RN doesn't support specific border styles per-edge
transition: true,
textWrap: true,
backdropFilter: true,
WebkitBackdropFilter: true,
background: true,
backgroundAttachment: true,
backgroundBlendMode: true,
backgroundClip: true,
backgroundColor: true,
backgroundImage: true,
backgroundOrigin: true,
backgroundPosition: true,
backgroundRepeat: true,
backgroundSize: true,
borderBottomStyle: true,
borderImage: true,
borderLeftStyle: true,
borderRightStyle: true,
borderTopStyle: true,
caretColor: true,
clipPath: true,
contain: true,
containerType: true,
content: true,
cursor: true,
float: true,
mask: true,
maskBorder: true,
maskBorderMode: true,
maskBorderOutset: true,
maskBorderRepeat: true,
maskBorderSlice: true,
maskBorderSource: true,
maskBorderWidth: true,
maskClip: true,
maskComposite: true,
maskImage: true,
maskMode: true,
maskOrigin: true,
maskPosition: true,
maskRepeat: true,
maskSize: true,
maskType: true,
objectFit: true,
objectPosition: true,
outlineOffset: true,
overflowBlock: true,
overflowInline: true,
overflowX: true,
overflowY: true,
pointerEvents: true,
scrollbarWidth: true,
textEmphasis: true,
touchAction: true,
transformStyle: true,
userSelect: true,
willChange: true,
...isAndroid ? {
elevationAndroid: true
} : {}
};
var stylePropsFont = {
fontFamily: true,
fontSize: true,
fontStyle: true,
fontWeight: true,
fontVariant: true,
letterSpacing: true,
lineHeight: true,
textTransform: true
};
var stylePropsTextOnly = {
...stylePropsFont,
textAlign: true,
textDecorationLine: true,
textDecorationStyle: true,
...textColors,
textShadowOffset: true,
textShadowRadius: true,
userSelect: true,
selectable: true,
verticalAlign: true,
whiteSpace: true,
wordWrap: true,
textOverflow: true,
textDecorationDistance: true,
cursor: true,
WebkitLineClamp: true,
WebkitBoxOrient: true
};
var stylePropsText = {
...stylePropsView,
...stylePropsTextOnly
};
// node_modules/@tamagui/helpers/dist/esm/withStaticProperties.mjs // node_modules/@tamagui/helpers/dist/esm/withStaticProperties.mjs
var import_react2 = __toESM(require("react"), 1); var import_react2 = __toESM(require("react"), 1);
var Decorated = Symbol(); var Decorated = Symbol();
@@ -755,7 +444,10 @@ var SizableText2 = (0, import_web4.styled)(import_web4.Text, {
} }
}); });
SizableText2.staticConfig.variants.fontFamily = { SizableText2.staticConfig.variants.fontFamily = {
"...": /* @__PURE__ */ __name((_val, extras) => { "...": /* @__PURE__ */ __name((val, extras) => {
if (val === "inherit") return {
fontFamily: "inherit"
};
const sizeProp = extras.props.size, fontSizeProp = extras.props.fontSize, size = sizeProp === "$true" && fontSizeProp ? fontSizeProp : extras.props.size || "$true"; const sizeProp = extras.props.size, fontSizeProp = extras.props.fontSize, size = sizeProp === "$true" && fontSizeProp ? fontSizeProp : extras.props.size || "$true";
return getFontSized(size, extras); return getFontSized(size, extras);
}, "...") }, "...")

View File

@@ -112,7 +112,10 @@ var SizableText2 = (0, import_web2.styled)(import_web2.Text, {
} }
}); });
SizableText2.staticConfig.variants.fontFamily = { SizableText2.staticConfig.variants.fontFamily = {
"...": /* @__PURE__ */ __name((_val, extras) => { "...": /* @__PURE__ */ __name((val, extras) => {
if (val === "inherit") return {
fontFamily: "inherit"
};
const sizeProp = extras.props.size, fontSizeProp = extras.props.fontSize, size = sizeProp === "$true" && fontSizeProp ? fontSizeProp : extras.props.size || "$true"; const sizeProp = extras.props.size, fontSizeProp = extras.props.fontSize, size = sizeProp === "$true" && fontSizeProp ? fontSizeProp : extras.props.size || "$true";
return getFontSized(size, extras); return getFontSized(size, extras);
}, "...") }, "...")

View File

@@ -1,4 +1,14 @@
{ {
"mobileProfile": {
"settings": "Einstellungen"
},
"readiness": {
"steps": {
"basicsDescription": "Grundlage für die Gäste-Info.",
"accessDescription": "Der Schlüssel für deine Gäste.",
"tasksDescription": "Sorgt für 3x mehr Interaktion."
}
},
"billing": { "billing": {
"title": "Pakete & Abrechnung", "title": "Pakete & Abrechnung",
"subtitle": "Verwalte deine gebuchten Pakete und behalte Laufzeiten im Blick.", "subtitle": "Verwalte deine gebuchten Pakete und behalte Laufzeiten im Blick.",
@@ -2244,6 +2254,9 @@
}, },
"mobileDashboard": { "mobileDashboard": {
"title": "Dashboard", "title": "Dashboard",
"shortcutAnalytics": "Analytics",
"quickActionsTitle": "Experience",
"readyForLiftoff": "Alles erledigt.",
"selectEvent": "Wähle ein Event, um fortzufahren", "selectEvent": "Wähle ein Event, um fortzufahren",
"emptyBadge": "Willkommen!", "emptyBadge": "Willkommen!",
"emptyTitle": "Willkommen! Lass uns dein erstes Event starten", "emptyTitle": "Willkommen! Lass uns dein erstes Event starten",
@@ -2629,7 +2642,9 @@
"themeLight": "Hell", "themeLight": "Hell",
"themeDark": "Dunkel", "themeDark": "Dunkel",
"themeSystem": "System", "themeSystem": "System",
"logout": "Abmelden" "logout": "Abmelden",
"logoutTitle": "Ausloggen",
"logoutHint": "Aus der App ausloggen"
}, },
"mobileSettings": { "mobileSettings": {
"title": "Einstellungen", "title": "Einstellungen",

View File

@@ -1,4 +1,14 @@
{ {
"mobileProfile": {
"settings": "Settings"
},
"readiness": {
"steps": {
"basicsDescription": "Foundation for guest info.",
"accessDescription": "Key for your guests.",
"tasksDescription": "Ensures 3x more engagement."
}
},
"billing": { "billing": {
"title": "Packages & billing", "title": "Packages & billing",
"subtitle": "Manage your purchased packages and track their durations.", "subtitle": "Manage your purchased packages and track their durations.",
@@ -2246,6 +2256,9 @@
}, },
"mobileDashboard": { "mobileDashboard": {
"title": "Dashboard", "title": "Dashboard",
"shortcutAnalytics": "Analytics",
"quickActionsTitle": "Experience",
"readyForLiftoff": "Ready for Liftoff",
"selectEvent": "Select an event to continue", "selectEvent": "Select an event to continue",
"emptyBadge": "Welcome aboard", "emptyBadge": "Welcome aboard",
"emptyTitle": "Welcome! Let's launch your first event", "emptyTitle": "Welcome! Let's launch your first event",
@@ -2631,7 +2644,9 @@
"themeLight": "Light", "themeLight": "Light",
"themeDark": "Dark", "themeDark": "Dark",
"themeSystem": "System", "themeSystem": "System",
"logout": "Log out" "logout": "Log out",
"logoutTitle": "Sign out",
"logoutHint": "Sign out from this app."
}, },
"mobileSettings": { "mobileSettings": {
"title": "Settings", "title": "Settings",

View File

@@ -1,19 +1,19 @@
import React from 'react'; import React from 'react';
import { useLocation, useNavigate, useParams } from 'react-router-dom'; import { useNavigate, useParams } from 'react-router-dom';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { useQuery } from '@tanstack/react-query'; import { useQuery } from '@tanstack/react-query';
import { Activity, Bell, CalendarDays, Camera, CheckCircle2, ChevronDown, Download, Image as ImageIcon, Layout, ListTodo, MapPin, Megaphone, MessageCircle, Pencil, QrCode, Settings, ShieldCheck, Smartphone, Sparkles, TrendingUp, Tv, Users, ArrowRight, Play, Clock, AlertCircle } from 'lucide-react'; import { Bell, CalendarDays, Camera, CheckCircle2, Download, Image as ImageIcon, Layout, ListTodo, Megaphone, QrCode, Settings, ShieldCheck, Sparkles, TrendingUp, Tv, Users, ArrowRight, AlertCircle } from 'lucide-react';
import { YStack, XStack } from '@tamagui/stacks'; import { YStack, XStack } from '@tamagui/stacks';
import { SizableText as Text } from '@tamagui/text'; import { SizableText as Text } from '@tamagui/text';
import { Pressable } from '@tamagui/react-native-web-lite'; import { Pressable } from '@tamagui/react-native-web-lite';
import { Image } from '@tamagui/image'; import { Image } from '@tamagui/image';
import { isSameDay, isPast, isFuture, parseISO, differenceInDays, startOfDay } from 'date-fns'; import { isSameDay, isPast, parseISO, differenceInDays, startOfDay } from 'date-fns';
import { MobileShell } from './components/MobileShell'; import { MobileShell } from './components/MobileShell';
import { ADMIN_EVENTS_PATH, adminPath } from '../constants'; import { ADMIN_EVENTS_PATH, adminPath } from '../constants';
import { useEventContext } from '../context/EventContext'; import { useEventContext } from '../context/EventContext';
import { getEventStats, EventStats, TenantEvent, getEventPhotos, TenantPhoto } from '../api'; import { getEventStats, EventStats, TenantEvent, getEventPhotos, TenantPhoto } from '../api';
import { formatEventDate, resolveEventDisplayName } from '../lib/events'; import { formatEventDate } from '../lib/events';
import { useAuth } from '../auth/context'; import { useAuth } from '../auth/context';
import { useAdminTheme } from './theme'; import { useAdminTheme } from './theme';
import { buildLimitWarnings } from '../lib/limitWarnings'; import { buildLimitWarnings } from '../lib/limitWarnings';
@@ -172,8 +172,6 @@ export default function MobileDashboardPage() {
navigate(ADMIN_EVENTS_PATH, { replace: true }); navigate(ADMIN_EVENTS_PATH, { replace: true });
}, [navigate, shouldRedirectToSelector]); }, [navigate, shouldRedirectToSelector]);
const [eventSwitcherOpen, setEventSwitcherOpen] = React.useState(false);
// --- RENDER --- // --- RENDER ---
if (shouldRedirectToSelector) { if (shouldRedirectToSelector) {
@@ -391,7 +389,9 @@ function LifecycleHero({ event, stats, locale, navigate, onSwitch, canSwitch, re
{readiness.isReady && ( {readiness.isReady && (
<XStack alignItems="center" space="$2"> <XStack alignItems="center" space="$2">
<CheckCircle2 size={18} color={theme.successText} /> <CheckCircle2 size={18} color={theme.successText} />
<Text fontSize="$sm" color={theme.successText} fontWeight="700">Ready for Liftoff</Text> <Text fontSize="$sm" color={theme.successText} fontWeight="700">
{t('management:mobileDashboard.readyForLiftoff', 'Ready for Liftoff')}
</Text>
</XStack> </XStack>
)} )}
</ModernCard> </ModernCard>
@@ -461,11 +461,11 @@ function UnifiedToolGrid({ event, navigate, permissions, isMember, isCompleted }
const sections = [ const sections = [
{ {
title: t('management:branding.badge', 'Experience'), title: t('management:mobileDashboard.quickActionsTitle', 'Experience'),
items: experienceItems, items: experienceItems,
}, },
{ {
title: t('management:workspace.hero.badge', 'Operations'), title: t('management:events.quickActions.title', 'Operations'),
items: operationsItems, items: operationsItems,
}, },
{ {

View File

@@ -10,7 +10,7 @@ import { Accordion } from '@tamagui/accordion';
import { ScrollView } from '@tamagui/scroll-view'; import { ScrollView } from '@tamagui/scroll-view';
import { ToggleGroup } from '@tamagui/toggle-group'; import { ToggleGroup } from '@tamagui/toggle-group';
import { MobileShell, HeaderActionButton } from './components/MobileShell'; import { MobileShell, HeaderActionButton } from './components/MobileShell';
import { MobileCard, CTAButton, SkeletonCard } from './components/Primitives'; import { MobileCard, CTAButton, SkeletonCard, ContentTabs } from './components/Primitives';
import { MobileField, MobileSelect } from './components/FormControls'; import { MobileField, MobileSelect } from './components/FormControls';
import { useEventContext } from '../context/EventContext'; import { useEventContext } from '../context/EventContext';
import { import {
@@ -279,7 +279,7 @@ export default function MobileEventControlRoomPage() {
const isMember = user?.role === 'member'; const isMember = user?.role === 'member';
const slug = slugParam ?? activeEvent?.slug ?? null; const slug = slugParam ?? activeEvent?.slug ?? null;
const online = useOnlineStatus(); const online = useOnlineStatus();
const { textStrong, text, muted, border, accentSoft, accent, danger, primary, surfaceMuted, surface } = useAdminTheme(); const { textStrong, muted, border, primary, surfaceMuted, surface } = useAdminTheme();
const [activeTab, setActiveTab] = React.useState<'moderation' | 'live'>('moderation'); const [activeTab, setActiveTab] = React.useState<'moderation' | 'live'>('moderation');
const [moderationPhotos, setModerationPhotos] = React.useState<TenantPhoto[]>([]); const [moderationPhotos, setModerationPhotos] = React.useState<TenantPhoto[]>([]);
@@ -342,8 +342,6 @@ export default function MobileEventControlRoomPage() {
const liveResetRef = React.useRef(false); const liveResetRef = React.useRef(false);
const [fallbackAttempted, setFallbackAttempted] = React.useState(false); const [fallbackAttempted, setFallbackAttempted] = React.useState(false);
const back = useBackNavigation(slug ? adminPath(`/mobile/events/${slug}`) : adminPath('/mobile/events')); const back = useBackNavigation(slug ? adminPath(`/mobile/events/${slug}`) : adminPath('/mobile/events'));
const infoBg = accentSoft;
const infoBorder = accent;
const activeFilterBg = primary; const activeFilterBg = primary;
const saveControlRoomSettings = React.useCallback( const saveControlRoomSettings = React.useCallback(
@@ -1022,17 +1020,6 @@ export default function MobileEventControlRoomPage() {
} }
} }
function resolveGalleryLabel(status?: string | null): string {
const key = status ?? 'pending';
const fallbackMap: Record<string, string> = {
approved: 'Gallery approved',
pending: 'Gallery pending',
rejected: 'Gallery rejected',
hidden: 'Hidden',
};
return t(`liveShowQueue.galleryStatus.${key}`, fallbackMap[key] ?? key);
}
function resolveLiveLabel(status?: string | null): string { function resolveLiveLabel(status?: string | null): string {
const key = normalizeLiveStatus(status); const key = normalizeLiveStatus(status);
return t(`liveShowQueue.status.${key}`, key); return t(`liveShowQueue.status.${key}`, key);
@@ -1078,24 +1065,10 @@ export default function MobileEventControlRoomPage() {
onBack={back} onBack={back}
headerActions={headerActions} headerActions={headerActions}
> >
<XStack space="$2"> <ContentTabs
{([ value={activeTab}
{ key: 'moderation', label: t('controlRoom.tabs.moderation', 'Moderation') }, onValueChange={(val) => setActiveTab(val as 'moderation' | 'live')}
{ key: 'live', label: t('controlRoom.tabs.live', 'Live Show') }, header={(
] as const).map((tab) => (
<Pressable key={tab.key} onPress={() => setActiveTab(tab.key)} style={{ flex: 1 }}>
<MobileCard
backgroundColor={activeTab === tab.key ? infoBg : 'transparent'}
borderColor={activeTab === tab.key ? infoBorder : border}
padding="$2.5"
>
<Text fontSize="$sm" fontWeight="700" textAlign="center" color={textStrong}>
{tab.label}
</Text>
</MobileCard>
</Pressable>
))}
</XStack>
<MobileCard> <MobileCard>
<Accordion type="single" collapsible> <Accordion type="single" collapsible>
@@ -1360,8 +1333,12 @@ export default function MobileEventControlRoomPage() {
</Accordion.Item> </Accordion.Item>
</Accordion> </Accordion>
</MobileCard> </MobileCard>
)}
{activeTab === 'moderation' ? ( tabs={[
{
value: 'moderation',
label: t('controlRoom.tabs.moderation', 'Moderation'),
content: (
<YStack space="$2"> <YStack space="$2">
{queuedEventCount > 0 ? ( {queuedEventCount > 0 ? (
<MobileCard> <MobileCard>
@@ -1555,7 +1532,12 @@ export default function MobileEventControlRoomPage() {
</MobileCard> </MobileCard>
) : null} ) : null}
</YStack> </YStack>
) : ( ),
},
{
value: 'live',
label: t('controlRoom.tabs.live', 'Live Show'),
content: (
<YStack space="$2"> <YStack space="$2">
<MobileCard borderColor={border} backgroundColor="transparent"> <MobileCard borderColor={border} backgroundColor="transparent">
<Text fontSize="$sm" color={muted}> <Text fontSize="$sm" color={muted}>
@@ -1744,7 +1726,10 @@ export default function MobileEventControlRoomPage() {
</MobileCard> </MobileCard>
) : null} ) : null}
</YStack> </YStack>
)} ),
},
]}
/>
<LegalConsentSheet <LegalConsentSheet
open={consentOpen} open={consentOpen}

View File

@@ -206,7 +206,7 @@ export default function MobileProfilePage() {
backgroundColor={surfaceMuted} backgroundColor={surfaceMuted}
> >
<Text fontSize="$xs" fontWeight="800" color={textColor}> <Text fontSize="$xs" fontWeight="800" color={textColor}>
{t('mobileProfile.preferences', 'Preferences')} {t('mobileProfile.settings', 'Preferences')}
</Text> </Text>
</XStack> </XStack>
<YGroup {...({ borderRadius: "$4", borderWidth: 1, borderColor: borderColor, overflow: "hidden" } as any)}> <YGroup {...({ borderRadius: "$4", borderWidth: 1, borderColor: borderColor, overflow: "hidden" } as any)}>

View File

@@ -143,7 +143,7 @@ export function MobileShell({ title, subtitle, children, activeTab, onBack, head
const EventContextPill = () => { const EventContextPill = () => {
if (!effectiveActive || isEventsIndex || isCompactHeader) { if (!effectiveActive || isEventsIndex || isCompactHeader) {
return ( return (
<Text fontSize="$md" fontWeight="800" fontFamily="$display" color="white"> <Text fontSize="$md" fontWeight="700" fontFamily="$display" color="white">
{pageTitle} {pageTitle}
</Text> </Text>
); );
@@ -153,7 +153,14 @@ export function MobileShell({ title, subtitle, children, activeTab, onBack, head
if (!canSwitchEvents) { if (!canSwitchEvents) {
return ( return (
<Text fontSize="$sm" fontWeight="800" color="white" numberOfLines={1} ellipsizeMode="tail"> <Text
fontSize="$lg"
fontWeight="700"
fontFamily="$display"
color="white"
numberOfLines={1}
ellipsizeMode="tail"
>
{displayName} {displayName}
</Text> </Text>
); );

View File

@@ -2,7 +2,8 @@ import React from 'react';
import { YStack, XStack } from '@tamagui/stacks'; import { YStack, XStack } from '@tamagui/stacks';
import { SizableText as Text } from '@tamagui/text'; import { SizableText as Text } from '@tamagui/text';
import { Pressable } from '@tamagui/react-native-web-lite'; import { Pressable } from '@tamagui/react-native-web-lite';
import { ADMIN_GRADIENTS, useAdminTheme } from '../theme'; import { Tabs, Separator } from 'tamagui';
import { useAdminTheme } from '../theme';
import { withAlpha } from './colors'; import { withAlpha } from './colors';
export function MobileCard({ export function MobileCard({
@@ -161,7 +162,7 @@ export function KpiTile({
note?: string; note?: string;
color?: string; color?: string;
}) { }) {
const { surfaceMuted, textStrong, textMuted, primary, accentSoft } = useAdminTheme(); const { textStrong, textMuted, primary, accentSoft } = useAdminTheme();
const iconBg = color ? withAlpha(color, 0.12) : accentSoft; const iconBg = color ? withAlpha(color, 0.12) : accentSoft;
const iconColor = color || primary; const iconColor = color || primary;
@@ -207,7 +208,7 @@ export function KpiStrip({
note?: string; note?: string;
}> }>
}) { }) {
const { glassSurface, border, textStrong, textMuted, primary, accentSoft } = useAdminTheme(); const { glassSurface, border, textStrong, textMuted, primary } = useAdminTheme();
return ( return (
<YStack <YStack
@@ -402,3 +403,63 @@ export function FloatingActionButton({
</Pressable> </Pressable>
); );
} }
export function ContentTabs({
value,
onValueChange,
tabs,
header,
}: {
value: string;
onValueChange: (val: string) => void;
tabs: { value: string; label: string; content: React.ReactNode }[];
header?: React.ReactNode;
}) {
const { border, muted, primary } = useAdminTheme();
return (
<Tabs
defaultValue={value}
value={value}
onValueChange={onValueChange}
orientation="horizontal"
flexDirection="column"
borderRadius="$4"
borderWidth={1}
borderColor={border}
overflow="hidden"
>
<Tabs.List separator={<Separator vertical />} disablePassBorderRadius="bottom" backgroundColor="$surface">
{tabs.map((tab) => (
<Tabs.Tab
key={tab.value}
value={tab.value}
flex={1}
unstyled
paddingVertical="$3"
alignItems="center"
justifyContent="center"
backgroundColor={value === tab.value ? primary : 'transparent'}
hoverStyle={{ backgroundColor: value === tab.value ? primary : '$backgroundHover' }}
>
<Text
fontSize="$sm"
fontWeight={value === tab.value ? '700' : '500'}
color={value === tab.value ? '#fff' : muted}
>
{tab.label}
</Text>
</Tabs.Tab>
))}
</Tabs.List>
{header}
{tabs.map((tab) => (
<Tabs.Content key={tab.value} value={tab.value}>
{tab.content}
</Tabs.Content>
))}
</Tabs>
);
}

View File

@@ -55,7 +55,7 @@ export function MobileScaffold({ title, onBack, rightSlot, children, footer }: M
<Text /> <Text />
)} )}
</XStack> </XStack>
<Text fontSize="$lg" fontWeight="800" color={text}> <Text fontSize="$lg" fontWeight="700" fontFamily="$display" color={text}>
{title} {title}
</Text> </Text>
<XStack minWidth={40} justifyContent="flex-end"> <XStack minWidth={40} justifyContent="flex-end">

View File

@@ -1,5 +1,4 @@
import { TenantEvent } from '../../api'; import { TenantEvent } from '../../api';
import { adminPath } from '../../constants';
export type ReadinessStep = { export type ReadinessStep = {
id: string; id: string;
@@ -43,7 +42,7 @@ export function useEventReadiness(event: TenantEvent | null, t: (key: string, fa
{ {
id: 'basics', id: 'basics',
label: t('management:events.form.date', 'Datum & Ort'), label: t('management:events.form.date', 'Datum & Ort'),
description: 'Grundlage für die Gäste-Info.', description: t('management:readiness.steps.basicsDescription', 'Grundlage für die Gäste-Info.'),
isComplete: hasDate && hasLocation, isComplete: hasDate && hasLocation,
ctaLabel: t('management:events.actions.edit', 'Bearbeiten'), ctaLabel: t('management:events.actions.edit', 'Bearbeiten'),
targetPath: `/mobile/events/${event.slug}/edit`, targetPath: `/mobile/events/${event.slug}/edit`,
@@ -52,7 +51,7 @@ export function useEventReadiness(event: TenantEvent | null, t: (key: string, fa
{ {
id: 'access', id: 'access',
label: t('management:invites.badge', 'QR-Codes'), label: t('management:invites.badge', 'QR-Codes'),
description: 'Der Schlüssel für deine Gäste.', description: t('management:readiness.steps.accessDescription', 'Der Schlüssel für deine Gäste.'),
ctaLabel: t('management:invites.actions.create', 'QR-Code erstellen'), ctaLabel: t('management:invites.actions.create', 'QR-Code erstellen'),
isComplete: hasInvite, isComplete: hasInvite,
targetPath: `/mobile/events/${event.slug}/qr`, targetPath: `/mobile/events/${event.slug}/qr`,
@@ -64,7 +63,7 @@ export function useEventReadiness(event: TenantEvent | null, t: (key: string, fa
steps.push({ steps.push({
id: 'tasks', id: 'tasks',
label: t('management:tasks.badge', 'Fotoaufgaben'), label: t('management:tasks.badge', 'Fotoaufgaben'),
description: 'Sorgt für 3x mehr Interaktion.', description: t('management:readiness.steps.tasksDescription', 'Sorgt für 3x mehr Interaktion.'),
isComplete: hasTasks, isComplete: hasTasks,
ctaLabel: t('management:tasks.actions.assign', 'Fotoaufgaben hinzufügen'), ctaLabel: t('management:tasks.actions.assign', 'Fotoaufgaben hinzufügen'),
targetPath: `/mobile/events/${event.slug}/tasks`, targetPath: `/mobile/events/${event.slug}/tasks`,

View File

@@ -102,12 +102,12 @@ const fonts = {
}, },
heading: { heading: {
...defaultConfig.fonts.heading, ...defaultConfig.fonts.heading,
family: 'Archivo Black', family: 'Playfair Display',
weight: sharedWeights, weight: sharedWeights,
}, },
display: { display: {
...defaultConfig.fonts.heading, ...defaultConfig.fonts.heading,
family: 'Archivo Black', family: 'Playfair Display',
weight: sharedWeights, weight: sharedWeights,
}, },
}; };