@blinkk/root-cms 3.0.1-alpha.0 → 3.0.1-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app.js +12 -6
- package/dist/chunk-ATPWU3CU.js +921 -0
- package/dist/chunk-CRK7N6RR.js +298 -0
- package/dist/{chunk-YMUZ5H5C.js → chunk-F4SODS5S.js} +108 -297
- package/dist/{chunk-MSJGHSR6.js → chunk-MAZA5B27.js} +23 -27
- package/dist/chunk-TRM4MQHU.js +1180 -0
- package/dist/{chunk-KDXHFMIH.js → chunk-XLX37FRL.js} +3 -0
- package/dist/cli.js +3 -2
- package/dist/{client-cP6yMgT8.d.ts → client-1puwLgNx.d.ts} +317 -24
- package/dist/client.d.ts +2 -2
- package/dist/client.js +2 -1
- package/dist/core.d.ts +3 -3
- package/dist/core.js +8 -1
- package/dist/functions.js +3 -2
- package/dist/{generate-types-MHWSSOWV.js → generate-types-SPV7I3A5.js} +1 -1
- package/dist/plugin.d.ts +2 -2
- package/dist/plugin.js +369 -79
- package/dist/project.d.ts +16 -3
- package/dist/project.js +3 -1
- package/dist/richtext.d.ts +25 -18
- package/dist/richtext.js +98 -43
- package/dist/{schema-D7MOj-YC.d.ts → schema-Db_xODoi.d.ts} +66 -1
- package/dist/ui/signin.css +1 -1
- package/dist/ui/signin.js +3 -3
- package/dist/ui/ui.css +1 -1
- package/dist/ui/ui.js +259 -175
- package/dist/ui/ui.js.LEGAL.txt +16 -3
- package/package.json +12 -8
- package/dist/ai-OZY3JXDH.js +0 -19
- package/dist/altText-RDKJNVGH.js +0 -7
- package/dist/chunk-H6ZKML2S.js +0 -157
- package/dist/chunk-N4Z3O53K.js +0 -191
- package/dist/chunk-T5UK2H24.js +0 -419
package/dist/richtext.js
CHANGED
|
@@ -1,70 +1,99 @@
|
|
|
1
1
|
import "./chunk-MLKGABMK.js";
|
|
2
2
|
|
|
3
3
|
// core/richtext.tsx
|
|
4
|
-
import { useTranslations } from "@blinkk/root";
|
|
5
|
-
import { createContext } from "preact";
|
|
4
|
+
import { StringParamsProvider, useTranslations } from "@blinkk/root";
|
|
5
|
+
import { Component, createContext } from "preact";
|
|
6
6
|
import { useContext } from "preact/hooks";
|
|
7
|
-
import {
|
|
7
|
+
import { renderToString } from "preact-render-to-string";
|
|
8
|
+
import { jsx, jsxs } from "preact/jsx-runtime";
|
|
8
9
|
var RichTextContext = createContext({});
|
|
9
10
|
function useRichTextContext() {
|
|
10
11
|
return useContext(RichTextContext);
|
|
11
12
|
}
|
|
13
|
+
var RichTextComponentMapContext = createContext({});
|
|
14
|
+
function useRichTextContextComponentMap() {
|
|
15
|
+
return useContext(RichTextComponentMapContext);
|
|
16
|
+
}
|
|
17
|
+
function useRichTextTranslations() {
|
|
18
|
+
const ctx = useRichTextContext();
|
|
19
|
+
if (ctx.t) {
|
|
20
|
+
return ctx.t;
|
|
21
|
+
}
|
|
22
|
+
return useTranslations();
|
|
23
|
+
}
|
|
12
24
|
function RichText(props) {
|
|
25
|
+
const blocks = props.data?.blocks || [];
|
|
26
|
+
if (blocks.length === 0) {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
13
29
|
const richTextContext = useRichTextContext();
|
|
14
|
-
const
|
|
15
|
-
delimiter: RichText.DelimiterBlock,
|
|
30
|
+
const componentMap = {
|
|
16
31
|
heading: RichText.HeadingBlock,
|
|
17
32
|
html: RichText.HtmlBlock,
|
|
18
33
|
image: RichText.ImageBlock,
|
|
19
34
|
orderedList: RichText.ListBlock,
|
|
20
35
|
paragraph: RichText.ParagraphBlock,
|
|
21
|
-
quote: RichText.QuoteBlock,
|
|
22
36
|
table: RichText.TableBlock,
|
|
23
37
|
unorderedList: RichText.ListBlock,
|
|
24
38
|
...richTextContext.components,
|
|
25
39
|
...props.components
|
|
26
40
|
};
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
return false;
|
|
31
|
-
}
|
|
32
|
-
if (!(blockType in components)) {
|
|
33
|
-
console.warn(`ignoring unknown richtext type: "${blockType}"`);
|
|
34
|
-
return false;
|
|
35
|
-
}
|
|
36
|
-
return true;
|
|
37
|
-
});
|
|
38
|
-
return /* @__PURE__ */ jsx(Fragment, { children: blocks.map((block) => {
|
|
39
|
-
const Block = components[block.type];
|
|
40
|
-
return /* @__PURE__ */ jsx(Block, { ...block });
|
|
41
|
-
}) });
|
|
41
|
+
return /* @__PURE__ */ jsx(RichTextComponentMapContext.Provider, { value: componentMap, children: blocks.map((block) => {
|
|
42
|
+
return /* @__PURE__ */ jsx(RichText.Block, { ...block });
|
|
43
|
+
}).filter((value) => !!value) });
|
|
42
44
|
}
|
|
43
|
-
RichText.
|
|
44
|
-
|
|
45
|
+
RichText.Block = (props) => {
|
|
46
|
+
const block = props;
|
|
47
|
+
const blockType = block?.type;
|
|
48
|
+
if (!blockType) {
|
|
45
49
|
return null;
|
|
46
50
|
}
|
|
47
|
-
const
|
|
48
|
-
|
|
51
|
+
const componentMap = useRichTextContextComponentMap();
|
|
52
|
+
const BlockComponent = componentMap[blockType];
|
|
53
|
+
if (!BlockComponent) {
|
|
54
|
+
console.warn(`[RichText] ignoring unknown richtext type: "${blockType}"`);
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
return /* @__PURE__ */ jsx(
|
|
58
|
+
InlineComponentRenderer,
|
|
59
|
+
{
|
|
60
|
+
block,
|
|
61
|
+
componentMap,
|
|
62
|
+
BlockComponent
|
|
63
|
+
}
|
|
64
|
+
);
|
|
49
65
|
};
|
|
50
|
-
|
|
51
|
-
|
|
66
|
+
var InlineComponentRenderer = class extends Component {
|
|
67
|
+
render() {
|
|
68
|
+
const { block, componentMap, BlockComponent } = this.props;
|
|
69
|
+
const stringParams = collectInlineComponentParams(
|
|
70
|
+
block,
|
|
71
|
+
componentMap,
|
|
72
|
+
this.context
|
|
73
|
+
);
|
|
74
|
+
if (stringParams) {
|
|
75
|
+
return /* @__PURE__ */ jsx(StringParamsProvider, { value: stringParams, children: /* @__PURE__ */ jsx(BlockComponent, { ...block }) });
|
|
76
|
+
}
|
|
77
|
+
return /* @__PURE__ */ jsx(BlockComponent, { ...block });
|
|
78
|
+
}
|
|
52
79
|
};
|
|
53
|
-
RichText.
|
|
80
|
+
RichText.ParagraphBlock = (props) => {
|
|
54
81
|
if (!props.data?.text) {
|
|
55
82
|
return null;
|
|
56
83
|
}
|
|
57
|
-
const t =
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
return /* @__PURE__ */ jsx(Component, { dangerouslySetInnerHTML: { __html: t(props.data.text) } });
|
|
84
|
+
const t = useRichTextTranslations();
|
|
85
|
+
const html = t(props.data.text);
|
|
86
|
+
return /* @__PURE__ */ jsx("p", { dangerouslySetInnerHTML: { __html: html } });
|
|
61
87
|
};
|
|
62
|
-
RichText.
|
|
88
|
+
RichText.HeadingBlock = (props) => {
|
|
63
89
|
if (!props.data?.text) {
|
|
64
90
|
return null;
|
|
65
91
|
}
|
|
66
|
-
const t =
|
|
67
|
-
|
|
92
|
+
const t = useRichTextTranslations();
|
|
93
|
+
const level = props.data.level || 2;
|
|
94
|
+
const Component2 = `h${level}`;
|
|
95
|
+
const html = t(props.data.text);
|
|
96
|
+
return /* @__PURE__ */ jsx(Component2, { dangerouslySetInnerHTML: { __html: html } });
|
|
68
97
|
};
|
|
69
98
|
RichText.ListBlock = (props) => {
|
|
70
99
|
if (!props.data?.items?.length) {
|
|
@@ -74,20 +103,20 @@ RichText.ListBlock = (props) => {
|
|
|
74
103
|
if (!style) {
|
|
75
104
|
style = props.type === "orderedList" ? "ordered" : "unordered";
|
|
76
105
|
}
|
|
77
|
-
const
|
|
106
|
+
const Component2 = style === "ordered" ? "ol" : "ul";
|
|
78
107
|
const items = props.data.items;
|
|
79
|
-
return /* @__PURE__ */ jsx(
|
|
108
|
+
return /* @__PURE__ */ jsx(Component2, { children: items.map((item) => {
|
|
80
109
|
if (item.content || item.items?.length) {
|
|
81
110
|
return /* @__PURE__ */ jsxs("li", { children: [
|
|
82
111
|
item.content && /* @__PURE__ */ jsx(
|
|
83
|
-
RichText.
|
|
112
|
+
RichText.Block,
|
|
84
113
|
{
|
|
85
114
|
type: "paragraph",
|
|
86
|
-
data: { text: item.content }
|
|
115
|
+
data: { text: item.content, components: item.components }
|
|
87
116
|
}
|
|
88
117
|
),
|
|
89
118
|
item.items && item.items.length > 0 && /* @__PURE__ */ jsx(
|
|
90
|
-
RichText.
|
|
119
|
+
RichText.Block,
|
|
91
120
|
{
|
|
92
121
|
type: props.type,
|
|
93
122
|
data: { style, items: item.items }
|
|
@@ -109,7 +138,8 @@ RichText.ImageBlock = (props) => {
|
|
|
109
138
|
return /* @__PURE__ */ jsx("img", { src: imageUrl, width, height, alt });
|
|
110
139
|
};
|
|
111
140
|
RichText.HtmlBlock = (props) => {
|
|
112
|
-
const
|
|
141
|
+
const t = useRichTextTranslations();
|
|
142
|
+
const html = t(props.data?.html || "");
|
|
113
143
|
if (!html) {
|
|
114
144
|
return null;
|
|
115
145
|
}
|
|
@@ -122,8 +152,7 @@ RichText.TableBlock = (props) => {
|
|
|
122
152
|
return null;
|
|
123
153
|
}
|
|
124
154
|
return /* @__PURE__ */ jsx("table", { children: /* @__PURE__ */ jsx("tbody", { children: rows.map((row, rowIndex) => /* @__PURE__ */ jsx("tr", { children: row.cells.map((cell, cellIndex) => {
|
|
125
|
-
const
|
|
126
|
-
const Cell = isHeader ? "th" : "td";
|
|
155
|
+
const Cell = cell.type === "header" ? "th" : "td";
|
|
127
156
|
return /* @__PURE__ */ jsx(Cell, { children: /* @__PURE__ */ jsx(
|
|
128
157
|
RichText,
|
|
129
158
|
{
|
|
@@ -146,8 +175,34 @@ function toNumber(input) {
|
|
|
146
175
|
}
|
|
147
176
|
return parsedNumber;
|
|
148
177
|
}
|
|
178
|
+
function testContent(data) {
|
|
179
|
+
return data?.blocks?.length > 0;
|
|
180
|
+
}
|
|
181
|
+
function collectInlineComponentParams(block, componentMap, renderContext) {
|
|
182
|
+
const components = block?.data?.components || {};
|
|
183
|
+
if (Object.keys(components).length === 0) {
|
|
184
|
+
return null;
|
|
185
|
+
}
|
|
186
|
+
const params = {};
|
|
187
|
+
for (const [componentId, component] of Object.entries(components)) {
|
|
188
|
+
const Component2 = componentMap[component.type];
|
|
189
|
+
if (Component2) {
|
|
190
|
+
const key = `${component.type}:${componentId}`;
|
|
191
|
+
params[key] = renderToString(
|
|
192
|
+
/* @__PURE__ */ jsx(Component2, { ...component.data }),
|
|
193
|
+
renderContext
|
|
194
|
+
);
|
|
195
|
+
} else {
|
|
196
|
+
console.warn(
|
|
197
|
+
`[RichText] could not find inline component for type: "${component.type}"`
|
|
198
|
+
);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
return params;
|
|
202
|
+
}
|
|
149
203
|
export {
|
|
150
204
|
RichText,
|
|
151
205
|
RichTextContext,
|
|
206
|
+
testContent,
|
|
152
207
|
useRichTextContext
|
|
153
208
|
};
|
|
@@ -155,6 +155,11 @@ type ArrayField = CommonFieldProps & {
|
|
|
155
155
|
* Label to use for the "add item" button. Defaults to `Add`.
|
|
156
156
|
*/
|
|
157
157
|
buttonLabel?: string;
|
|
158
|
+
/**
|
|
159
|
+
* Whether array items should be open (expanded) by default. Defaults to
|
|
160
|
+
* `false`, meaning items start collapsed.
|
|
161
|
+
*/
|
|
162
|
+
defaultOpen?: boolean;
|
|
158
163
|
};
|
|
159
164
|
declare function array(field: Omit<ArrayField, 'type'>): ArrayField;
|
|
160
165
|
/**
|
|
@@ -174,6 +179,13 @@ interface SchemaPattern {
|
|
|
174
179
|
}
|
|
175
180
|
type OneOfField = CommonFieldProps & {
|
|
176
181
|
type: 'oneof';
|
|
182
|
+
/**
|
|
183
|
+
* UI variant for the oneOf field.
|
|
184
|
+
* - `dropdown` (default): A `Select` dropdown for choosing the type.
|
|
185
|
+
* - `picker`: A `Button` that opens a modal with searchable cards. Use this
|
|
186
|
+
* variant when types declare presets or thumbnail images.
|
|
187
|
+
*/
|
|
188
|
+
variant?: 'dropdown' | 'picker';
|
|
177
189
|
/**
|
|
178
190
|
* Schema types to include in the oneOf field. Can be:
|
|
179
191
|
* - An array of Schema objects
|
|
@@ -226,6 +238,25 @@ type Field = StringField | NumberField | DateField | DateTimeField | BooleanFiel
|
|
|
226
238
|
*/
|
|
227
239
|
type FieldWithId = Field;
|
|
228
240
|
type ObjectLikeField = ImageField | FileField | ObjectField | OneOfField | ReferenceField;
|
|
241
|
+
interface SchemaPreset<T = Record<string, any>> {
|
|
242
|
+
/** Unique identifier for the preset within the schema. */
|
|
243
|
+
id: string;
|
|
244
|
+
/** Display title for the preset. Defaults to the preset id. */
|
|
245
|
+
label?: string;
|
|
246
|
+
/** Description shown below the title in the picker. */
|
|
247
|
+
description?: string;
|
|
248
|
+
/** Thumbnail image (URL or absolute /-path) for the picker. */
|
|
249
|
+
image?: string;
|
|
250
|
+
/**
|
|
251
|
+
* Field values to prefill. Deep-merged into the schema's default value
|
|
252
|
+
* (preset values override defaults). `_type` is set automatically. The
|
|
253
|
+
* preset id is NOT persisted — presets are purely a prefill mechanism.
|
|
254
|
+
*
|
|
255
|
+
* Pass a generated fields type as the generic parameter `T` to
|
|
256
|
+
* type-check the keys against the schema's fields.
|
|
257
|
+
*/
|
|
258
|
+
data?: T;
|
|
259
|
+
}
|
|
229
260
|
interface Schema {
|
|
230
261
|
/** The name of the content type. Used as the field key. */
|
|
231
262
|
name: string;
|
|
@@ -233,6 +264,19 @@ interface Schema {
|
|
|
233
264
|
label?: string;
|
|
234
265
|
/** The description of the content type. Appears in CMS menus. */
|
|
235
266
|
description?: string;
|
|
267
|
+
/**
|
|
268
|
+
* Optional thumbnail image (URL or absolute /-path) used to represent this
|
|
269
|
+
* schema in the picker UI for `oneof` fields with `variant: 'picker'`.
|
|
270
|
+
*/
|
|
271
|
+
image?: string;
|
|
272
|
+
/**
|
|
273
|
+
* Optional preset prefill configurations for use in the picker UI.
|
|
274
|
+
*
|
|
275
|
+
* Each preset appears in the picker as a separate selectable card alongside
|
|
276
|
+
* the schema's "blank" card. Selecting a preset sets `_type` to the schema's
|
|
277
|
+
* `name` and merges `data` over the schema's default field values.
|
|
278
|
+
*/
|
|
279
|
+
presets?: SchemaPreset<any>[];
|
|
236
280
|
/** Fields describe the structure of the content. */
|
|
237
281
|
fields: FieldWithId[];
|
|
238
282
|
/** Defines the preview displayed within the CMS UI. Overrides the `preview` definition for the `array` field. */
|
|
@@ -267,6 +311,24 @@ type SchemaWithTypes = Schema & {
|
|
|
267
311
|
declare function defineSchema(schema: Schema): Schema;
|
|
268
312
|
/** Defines the schema for a collection or reusable component. */
|
|
269
313
|
declare const define: typeof defineSchema;
|
|
314
|
+
/**
|
|
315
|
+
* Defines a preset for use within `schema.define({presets: [...]})`. The
|
|
316
|
+
* optional generic parameter `T` constrains the shape of the preset's `data`
|
|
317
|
+
* field. Pass an auto-generated fields type to enable type-safety:
|
|
318
|
+
*
|
|
319
|
+
* ```ts
|
|
320
|
+
* import type {HeroFields} from './generated/types.d.ts';
|
|
321
|
+
*
|
|
322
|
+
* schema.definePreset<HeroFields>({
|
|
323
|
+
* id: 'big',
|
|
324
|
+
* label: 'Big hero',
|
|
325
|
+
* data: {title: 'Welcome'},
|
|
326
|
+
* });
|
|
327
|
+
* ```
|
|
328
|
+
*/
|
|
329
|
+
declare function definePreset<T = Record<string, any>>(preset: SchemaPreset<T>): SchemaPreset<T>;
|
|
330
|
+
/** Alias for {@link definePreset}. */
|
|
331
|
+
declare const preset: typeof definePreset;
|
|
270
332
|
type Collection = SchemaWithTypes & {
|
|
271
333
|
/**
|
|
272
334
|
* The ID of the collection. This comes from the schema filename, e.g
|
|
@@ -410,6 +472,7 @@ type schema_ReferencesField = ReferencesField;
|
|
|
410
472
|
type schema_RichTextField = RichTextField;
|
|
411
473
|
type schema_Schema = Schema;
|
|
412
474
|
type schema_SchemaPattern = SchemaPattern;
|
|
475
|
+
type schema_SchemaPreset<T = Record<string, any>> = SchemaPreset<T>;
|
|
413
476
|
type schema_SchemaWithTypes = SchemaWithTypes;
|
|
414
477
|
type schema_SelectField = SelectField;
|
|
415
478
|
type schema_StringField = StringField;
|
|
@@ -420,6 +483,7 @@ declare const schema_date: typeof date;
|
|
|
420
483
|
declare const schema_datetime: typeof datetime;
|
|
421
484
|
declare const schema_define: typeof define;
|
|
422
485
|
declare const schema_defineCollection: typeof defineCollection;
|
|
486
|
+
declare const schema_definePreset: typeof definePreset;
|
|
423
487
|
declare const schema_defineSchema: typeof defineSchema;
|
|
424
488
|
declare const schema_file: typeof file;
|
|
425
489
|
declare const schema_glob: typeof glob;
|
|
@@ -428,13 +492,14 @@ declare const schema_multiselect: typeof multiselect;
|
|
|
428
492
|
declare const schema_number: typeof number;
|
|
429
493
|
declare const schema_object: typeof object;
|
|
430
494
|
declare const schema_oneOf: typeof oneOf;
|
|
495
|
+
declare const schema_preset: typeof preset;
|
|
431
496
|
declare const schema_reference: typeof reference;
|
|
432
497
|
declare const schema_references: typeof references;
|
|
433
498
|
declare const schema_richtext: typeof richtext;
|
|
434
499
|
declare const schema_select: typeof select;
|
|
435
500
|
declare const schema_string: typeof string;
|
|
436
501
|
declare namespace schema {
|
|
437
|
-
export { type schema_ArrayField as ArrayField, type schema_BooleanField as BooleanField, type schema_Collection as Collection, type schema_CommonFieldProps as CommonFieldProps, type schema_DateField as DateField, type schema_DateTimeField as DateTimeField, type schema_Field as Field, type schema_FieldWithId as FieldWithId, type schema_FileField as FileField, type schema_GlobOptions as GlobOptions, type schema_ImageField as ImageField, type schema_MultiSelectField as MultiSelectField, type schema_NumberField as NumberField, type schema_ObjectField as ObjectField, type schema_ObjectLikeField as ObjectLikeField, type schema_OneOfField as OneOfField, type schema_ReferenceField as ReferenceField, type schema_ReferencesField as ReferencesField, type schema_RichTextField as RichTextField, type schema_Schema as Schema, type schema_SchemaPattern as SchemaPattern, type schema_SchemaWithTypes as SchemaWithTypes, type schema_SelectField as SelectField, type schema_StringField as StringField, schema_array as array, schema_boolean as boolean, schema_collection as collection, schema_date as date, schema_datetime as datetime, schema_define as define, schema_defineCollection as defineCollection, schema_defineSchema as defineSchema, schema_file as file, schema_glob as glob, schema_image as image, schema_multiselect as multiselect, schema_number as number, schema_object as object, schema_oneOf as oneOf, schema_reference as reference, schema_references as references, schema_richtext as richtext, schema_select as select, schema_string as string };
|
|
502
|
+
export { type schema_ArrayField as ArrayField, type schema_BooleanField as BooleanField, type schema_Collection as Collection, type schema_CommonFieldProps as CommonFieldProps, type schema_DateField as DateField, type schema_DateTimeField as DateTimeField, type schema_Field as Field, type schema_FieldWithId as FieldWithId, type schema_FileField as FileField, type schema_GlobOptions as GlobOptions, type schema_ImageField as ImageField, type schema_MultiSelectField as MultiSelectField, type schema_NumberField as NumberField, type schema_ObjectField as ObjectField, type schema_ObjectLikeField as ObjectLikeField, type schema_OneOfField as OneOfField, type schema_ReferenceField as ReferenceField, type schema_ReferencesField as ReferencesField, type schema_RichTextField as RichTextField, type schema_Schema as Schema, type schema_SchemaPattern as SchemaPattern, type schema_SchemaPreset as SchemaPreset, type schema_SchemaWithTypes as SchemaWithTypes, type schema_SelectField as SelectField, type schema_StringField as StringField, schema_array as array, schema_boolean as boolean, schema_collection as collection, schema_date as date, schema_datetime as datetime, schema_define as define, schema_defineCollection as defineCollection, schema_definePreset as definePreset, schema_defineSchema as defineSchema, schema_file as file, schema_glob as glob, schema_image as image, schema_multiselect as multiselect, schema_number as number, schema_object as object, schema_oneOf as oneOf, schema_preset as preset, schema_reference as reference, schema_references as references, schema_richtext as richtext, schema_select as select, schema_string as string };
|
|
438
503
|
}
|
|
439
504
|
|
|
440
505
|
export { type Collection as C, type Schema as S, schema as s };
|
package/dist/ui/signin.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
:root{--font-family-default: "Inter", sans-serif;--font-family-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;--color-text-default: #333333;--color-border: #EFEFEF;--button-background-hover: #F5F5F5;--button-background-active: #E5E5E5}html{box-sizing:border-box;overflow-x:hidden;font-size:16px;line-height:1.5}*,*:before,*:after{box-sizing:inherit}html,body{font-family:var(--font-family-default);color:var(--color-text-default);height:100%;margin:0;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;scroll-behavior:smooth}img,picture,figure,video,canvas,svg,iframe{display:block;max-width:100%;height:auto;margin:0}a{color:inherit}select{color-scheme:light}h1,h2,h3,h4,h5,p{margin:0}body.menu\:open{overflow:hidden}#root{margin:0 auto;min-height:100vh;position:relative}.bootstrap{font-size:48px;font-weight:900;width:100%;height:100vh;display:flex;flex-direction:column;justify-content:center;align-items:center;text-align:center;padding:40px;gap:36px;position:relative}.bootstrap-error{font-size:14px;font-weight:400;line-height:20px;position:absolute;bottom:100px;left:0;right:0;text-align:center;animation:.5s forwards bootstrap-loading-error;animation-delay:1s;opacity:0;padding:0 24px}@keyframes bootstrap-loading-error{0%{opacity:0}to{opacity:1}}.signin{font-family:Google Sans,arial,sans-serif;text-align:center;padding:48px 20px;color:#3c4043}.signin__headline{margin-bottom:40px}.signin__headline__title{font-size:36px;line-height:1.3;font-weight:500;margin-bottom:20px}.signin__headline__body{font-size:18px;line-height:1.5;font-weight:500}.signin__button{-webkit-appearance:none;-moz-appearance:none;appearance:none;display:inline-flex;align-items:center;text-align:center;gap:12px;background:#fff;border:1px solid #dadce0;border-radius:4px;cursor:pointer;font-family:inherit;padding:0 12px;height:40px;box-sizing:border-box;transition:all .218s ease}.signin__warning{max-width:520px;margin:0 auto 40px;padding:12px;border:1px solid #fbbc04;border-radius:8px;background:#fff9db;color:#5f370e;font-size:14px;line-height:1.5}.signin__button:hover{border-color:#d2e3fc;background-color:#4285f40a}.signin__button__icon{width:18px;height:18px;background-color:#fff}.signin__button__label{font-size:14px;line-height:1;letter-spacing:.25px;font-weight:500;color:#3c4043}.signin__error{color:red;font-weight:700;text-align:center;max-width:60ch;margin:20px auto 0}
|
|
1
|
+
:root{--font-family-default: "Inter", sans-serif;--font-family-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;--color-text-default: #333333;--color-border: #EFEFEF;--button-background-hover: #F5F5F5;--button-background-active: #E5E5E5}html{box-sizing:border-box;overflow-x:hidden;font-size:16px;line-height:1.5}*,*:before,*:after{box-sizing:inherit}html,body{font-family:var(--font-family-default);color:var(--color-text-default);height:100%;margin:0;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;scroll-behavior:smooth}img,picture,figure,video,canvas,svg,iframe{display:block;max-width:100%;height:auto;margin:0}a{color:inherit}select{color-scheme:light}h1,h2,h3,h4,h5,p{margin:0}body.menu\:open{overflow:hidden}#root{margin:0 auto;min-height:100vh;position:relative}.bootstrap{font-size:48px;font-weight:900;width:100%;height:100vh;display:flex;flex-direction:column;justify-content:center;align-items:center;text-align:center;padding:40px;gap:36px;position:relative}.bootstrap-error{font-size:14px;font-weight:400;line-height:20px;position:absolute;bottom:100px;left:0;right:0;text-align:center;animation:.5s forwards bootstrap-loading-error;animation-delay:1s;opacity:0;padding:0 24px}.bootstrap--error{gap:16px}.bootstrap__error-title{font-size:48px;font-weight:900;line-height:1.1;margin:0}.bootstrap__error-message{color:#b00020;font-size:16px;font-weight:500;line-height:1.5;margin:0;max-width:640px}@keyframes bootstrap-loading-error{0%{opacity:0}to{opacity:1}}.signin{font-family:Google Sans,arial,sans-serif;text-align:center;padding:48px 20px;color:#3c4043}.signin__headline{margin-bottom:40px}.signin__headline__title{font-size:36px;line-height:1.3;font-weight:500;margin-bottom:20px}.signin__headline__body{font-size:18px;line-height:1.5;font-weight:500}.signin__button{-webkit-appearance:none;-moz-appearance:none;appearance:none;display:inline-flex;align-items:center;text-align:center;gap:12px;background:#fff;border:1px solid #dadce0;border-radius:4px;cursor:pointer;font-family:inherit;padding:0 12px;height:40px;box-sizing:border-box;transition:all .218s ease}.signin__warning{max-width:520px;margin:0 auto 40px;padding:12px;border:1px solid #fbbc04;border-radius:8px;background:#fff9db;color:#5f370e;font-size:14px;line-height:1.5}.signin__button:hover{border-color:#d2e3fc;background-color:#4285f40a}.signin__button__icon{width:18px;height:18px;background-color:#fff}.signin__button__label{font-size:14px;line-height:1;letter-spacing:.25px;font-weight:500;color:#3c4043}.signin__button--busy{cursor:default;opacity:.85;border-color:#d2e3fc;background-color:#4285f40a}.signin__button--busy:hover{background-color:#4285f40a}.signin__spinner{width:18px;height:18px;color:#4285f4;animation:signin-spin .7s linear infinite}@keyframes signin-spin{to{transform:rotate(360deg)}}.signin__error{color:red;font-weight:700;text-align:center;max-width:60ch;margin:20px auto 0}
|