@fuzdev/fuz_ui 0.206.9 → 0.208.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.
@@ -2,94 +2,57 @@ import type { Declaration } from './declaration.svelte.ts';
2
2
  import type { Library } from './library.svelte.ts';
3
3
  import type { Module } from './module.svelte.ts';
4
4
 
5
- export interface DeclarationSearchState {
6
- query: string;
7
- all: Array<Declaration>;
8
- filtered: Array<Declaration>;
9
- }
10
-
11
- export interface ApiSearchState {
12
- query: string;
13
- modules: {
14
- all: Array<Module>;
15
- filtered: Array<Module>;
16
- };
17
- declarations: {
18
- all: Array<Declaration>;
19
- filtered: Array<Declaration>;
20
- };
21
- }
22
-
23
5
  /**
24
- * Creates unified search state for the API index page (modules and declarations).
6
+ * Unified search state for the API index page (modules and declarations).
25
7
  */
26
- export const create_api_search = (library: Library): ApiSearchState => {
27
- let query = $state.raw('');
8
+ export class ApiSearchState {
9
+ readonly library: Library;
10
+
11
+ query: string = $state('');
28
12
 
29
- // Module filtering
30
- const all_modules = $derived(library.modules_sorted);
31
- const filtered_modules = $derived.by(() => {
32
- if (!query.trim()) return all_modules;
33
- const terms = query.trim().toLowerCase().split(/\s+/);
34
- return all_modules.filter((m) => {
13
+ readonly modules: Array<Module> = $derived.by(() => this.library.modules_sorted);
14
+
15
+ readonly modules_filtered: Array<Module> = $derived.by(() => {
16
+ if (!this.query.trim()) return this.modules;
17
+ const terms = this.query.trim().toLowerCase().split(/\s+/);
18
+ return this.modules.filter((m) => {
35
19
  const path_lower = m.path.toLowerCase();
36
20
  const comment_lower = m.module_comment?.toLowerCase() ?? '';
37
21
  return terms.every((term) => path_lower.includes(term) || comment_lower.includes(term));
38
22
  });
39
23
  });
40
24
 
41
- // Declaration filtering
42
- const all_declarations = $derived(library.declarations);
43
- const filtered_declarations = $derived.by(() => {
44
- const items = query.trim() ? library.search_declarations(query) : all_declarations;
25
+ readonly declarations: Array<Declaration> = $derived.by(() => this.library.declarations);
26
+
27
+ readonly declarations_filtered: Array<Declaration> = $derived.by(() => {
28
+ const items = this.query.trim()
29
+ ? this.library.search_declarations(this.query)
30
+ : this.declarations;
45
31
  // spread before sort — `items` may be the shared source array
46
32
  return [...items].sort((a, b) => a.name.localeCompare(b.name));
47
33
  });
48
34
 
49
- return {
50
- get query() {
51
- return query;
52
- },
53
- set query(v: string) {
54
- query = v;
55
- },
56
- modules: {
57
- get all() {
58
- return all_modules;
59
- },
60
- get filtered() {
61
- return filtered_modules;
62
- }
63
- },
64
- declarations: {
65
- get all() {
66
- return all_declarations;
67
- },
68
- get filtered() {
69
- return filtered_declarations;
70
- }
71
- }
72
- };
73
- };
35
+ constructor(library: Library) {
36
+ this.library = library;
37
+ }
38
+ }
74
39
 
75
40
  /**
76
- * Creates search state for module-specific declaration lists.
41
+ * Search state for a module-specific declaration list.
77
42
  */
78
- export const create_module_declaration_search = (
79
- declarations: Array<Declaration>
80
- ): DeclarationSearchState => {
81
- let query = $state.raw('');
43
+ export class DeclarationSearchState {
44
+ readonly declarations: Array<Declaration>;
82
45
 
83
- const all = $derived(declarations);
46
+ query: string = $state('');
84
47
 
85
- const filtered = $derived.by(() => {
86
- const trimmed_query = query.trim();
87
- // spread before sort — `all` is the shared source array
88
- if (!trimmed_query) return [...all].sort((a, b) => a.name.localeCompare(b.name));
48
+ readonly filtered: Array<Declaration> = $derived.by(() => {
49
+ const trimmed_query = this.query.trim();
50
+ // spread before sort — `declarations` is the shared source array
51
+ if (!trimmed_query) return [...this.declarations].sort((a, b) => a.name.localeCompare(b.name));
89
52
 
90
53
  const terms = trimmed_query.toLowerCase().split(/\s+/);
91
54
 
92
- const items = all.filter((d) => {
55
+ const items = this.declarations.filter((d) => {
93
56
  const name_lower = d.name.toLowerCase();
94
57
  const kind_lower = d.kind.toLowerCase();
95
58
  const module_path_lower = d.module_path.toLowerCase();
@@ -103,18 +66,7 @@ export const create_module_declaration_search = (
103
66
  return items.sort((a, b) => a.name.localeCompare(b.name));
104
67
  });
105
68
 
106
- return {
107
- get query() {
108
- return query;
109
- },
110
- set query(v: string) {
111
- query = v;
112
- },
113
- get all() {
114
- return all;
115
- },
116
- get filtered() {
117
- return filtered;
118
- }
119
- };
120
- };
69
+ constructor(declarations: Array<Declaration>) {
70
+ this.declarations = declarations;
71
+ }
72
+ }
package/src/lib/csp.ts CHANGED
@@ -254,7 +254,33 @@ const for_each_directive = <V>(
254
254
  }
255
255
  };
256
256
 
257
- export const COLOR_SCHEME_SCRIPT_HASH = 'sha256-QOxqn7EUzb3ydF9SALJoJGWSvywW9R0AfTDSenB83Z8=';
257
+ /**
258
+ * The exact body of the color-scheme loader `<script>` in `app.html`, the inline script
259
+ * `COLOR_SCHEME_SCRIPT_HASH` admits.
260
+ *
261
+ * The loader has to run before first paint to avoid a flash of the wrong scheme, so it is inline
262
+ * rather than a render-blocking `src`, and CSP admits it by hash. That makes its bytes
263
+ * load-bearing: whitespace, quoting, and trailing commas all move the hash, so a formatter that
264
+ * reflows `app.html` breaks the theme on every cold load with nothing but a console violation to
265
+ * show for it. Consumers can guard their own `app.html` against this constant.
266
+ */
267
+ export const COLOR_SCHEME_SCRIPT = `
268
+ document.documentElement.classList.add(
269
+ ((c) =>
270
+ c === 'dark' || (c !== 'light' && matchMedia('(prefers-color-scheme:dark)').matches)
271
+ ? 'dark'
272
+ : 'light')(localStorage.getItem('fuz:color-scheme'))
273
+ );
274
+ `;
275
+
276
+ /**
277
+ * The `sha256-` CSP source for `COLOR_SCHEME_SCRIPT`, carried by the `script-src` and
278
+ * `script-src-elem` defaults so the loader runs under the library CSP.
279
+ *
280
+ * Regenerate after any edit to `COLOR_SCHEME_SCRIPT` — `src/test/csp.color_scheme.test.ts`
281
+ * reports the expected value when the two disagree.
282
+ */
283
+ export const COLOR_SCHEME_SCRIPT_HASH = 'sha256-CkhymyixntvSTuePGizI3BFtnRFlWWg95YBmBOCFxfY=';
258
284
 
259
285
  /**
260
286
  * The library CSP directive defaults — directives enabled out of the box.
@@ -5,7 +5,8 @@ import type {
5
5
  ParameterJsonInput,
6
6
  ComponentPropJsonInput,
7
7
  OverloadJsonInput,
8
- Reactivity
8
+ Reactivity,
9
+ TypeJson
9
10
  } from 'svelte-docinfo/types.js';
10
11
  import { generateImport, getDisplayName } from 'svelte-docinfo/declaration-helpers.js';
11
12
  import { EMPTY_ARRAY } from '@fuzdev/fuz_util/array.ts';
@@ -34,7 +35,7 @@ const field = <T>(decl: DeclarationJsonInput, key: string): T | undefined =>
34
35
  * Computed properties are plain getters rather than `$derived` — see
35
36
  * `Library` for why.
36
37
  *
37
- * @see {@link https://github.com/ryanatkn/svelte-docinfo svelte-docinfo} for the analysis library
38
+ * @see {@link https://github.com/fuzdev/svelte-docinfo svelte-docinfo} for the analysis library
38
39
  * @see `DeclarationDetail.svelte` for the rendering component
39
40
  */
40
41
  export class Declaration {
@@ -86,8 +87,9 @@ export class Declaration {
86
87
  * Generated TypeScript import statement.
87
88
  */
88
89
  get import_statement(): string {
89
- // `generateImport` reads only `name`/`kind`/path, none of the defaulted
90
- // arrays, so asserting the parsed shape here is sound.
90
+ // `generateImport` reads only `name`/`kind`/`mergedValue`/path, none of
91
+ // the defaulted arrays, and treats an absent `mergedValue` as the stripped
92
+ // `false`, so asserting the parsed shape here is sound.
91
93
  return (this.#import_statement ??= generateImport(
92
94
  this.declaration_json as DeclarationJson,
93
95
  this.module_path,
@@ -122,6 +124,44 @@ export class Declaration {
122
124
  return this.declaration_json.typeSignature;
123
125
  }
124
126
 
127
+ /**
128
+ * Structured type tree beside `type_signature`, absent when the flat string
129
+ * is the whole story. Present on `variable` and `type` kinds only.
130
+ */
131
+ get type_info(): TypeJson | undefined {
132
+ return field<TypeJson>(this.declaration_json, 'typeInfo');
133
+ }
134
+
135
+ /**
136
+ * `type_info` prepared for rendering at the declaration itself. A type
137
+ * alias's tree carries the alias's own name at the root
138
+ * (`type A = 'a' | 'b'` → `{kind: 'union', alias: 'A', members: [...]}`),
139
+ * which `typeJsonToTokens` collapses to the bare name — right where `A` is
140
+ * composed into another type, circular at `A`'s own declaration. Strips
141
+ * that self-alias so the root expands into its members; every other tree
142
+ * passes through unchanged.
143
+ */
144
+ get type_info_expanded(): TypeJson | undefined {
145
+ const type_info = this.type_info;
146
+ if (
147
+ type_info &&
148
+ (type_info.kind === 'union' || type_info.kind === 'intersection') &&
149
+ type_info.alias === this.name
150
+ ) {
151
+ return { ...type_info, alias: undefined };
152
+ }
153
+ return type_info;
154
+ }
155
+
156
+ /**
157
+ * Default value documented via `@default`; the authoritative initializer
158
+ * (when human-readable) is in `type_signature`. Present on `variable` kind
159
+ * only — parameters, props, and members carry their own.
160
+ */
161
+ get default_value(): string | undefined {
162
+ return field<string>(this.declaration_json, 'defaultValue');
163
+ }
164
+
125
165
  get doc_comment(): string | undefined {
126
166
  return this.declaration_json.docComment;
127
167
  }
@@ -142,6 +182,14 @@ export class Declaration {
142
182
  return field<string>(this.declaration_json, 'returnType');
143
183
  }
144
184
 
185
+ /**
186
+ * Structured return type beside `return_type`, absent when the flat string
187
+ * is the whole story. Present on `function` kind only.
188
+ */
189
+ get return_type_info(): TypeJson | undefined {
190
+ return field<TypeJson>(this.declaration_json, 'returnTypeInfo');
191
+ }
192
+
145
193
  get return_description(): string | undefined {
146
194
  return field<string>(this.declaration_json, 'returnDescription');
147
195
  }
@@ -150,8 +198,8 @@ export class Declaration {
150
198
  return this.declaration_json.genericParams ?? EMPTY_ARRAY;
151
199
  }
152
200
 
153
- get extends_type(): string | Array<string> | undefined {
154
- return field<string | Array<string>>(this.declaration_json, 'extends');
201
+ get extends_types(): Array<string> | undefined {
202
+ return field<Array<string>>(this.declaration_json, 'extends');
155
203
  }
156
204
 
157
205
  get implements_types(): Array<string> | undefined {
@@ -182,11 +230,25 @@ export class Declaration {
182
230
  }
183
231
 
184
232
  /**
185
- * Intersection types whose properties are external (filtered out of props/members).
186
- * Present on `component` and `type` kinds.
233
+ * External types whose contributions are filtered out of props/members —
234
+ * the attribute bags a component forwards, however the author composed
235
+ * them (intersection, heritage clause, bare or indexed-access reference).
236
+ * On `interface`/`class` kinds it records the external reach of the
237
+ * heritage chain, whose contributions members (own-only) never enumerate.
238
+ * Present on `component`, `type`, `interface`, and `class` kinds.
239
+ */
240
+ get external_types(): Array<string> | undefined {
241
+ return field<Array<string>>(this.declaration_json, 'externalTypes');
242
+ }
243
+
244
+ /**
245
+ * Whether the exported name also carries a value meaning — a merged
246
+ * value+type symbol like `const Foo = z.strictObject({...})` beside
247
+ * `type Foo = z.infer<typeof Foo>`, where the type wins the declaration slot.
248
+ * Present on `type` and `interface` kinds.
187
249
  */
188
- get intersects(): Array<string> | undefined {
189
- return field<Array<string>>(this.declaration_json, 'intersects');
250
+ get merged_value(): boolean | undefined {
251
+ return field<boolean>(this.declaration_json, 'mergedValue');
190
252
  }
191
253
 
192
254
  /**
@@ -228,6 +290,15 @@ export class Declaration {
228
290
  return this.declaration_json.mutates;
229
291
  }
230
292
 
293
+ /**
294
+ * Internal-API marker from the `@internal` tag. Presence means the tag was
295
+ * written; an empty string is a bare tag with no trailing prose. A marker,
296
+ * not an exclusion — the declaration stays documented.
297
+ */
298
+ get internal_message(): string | undefined {
299
+ return this.declaration_json.internalMessage;
300
+ }
301
+
231
302
  /**
232
303
  * Svelte reactivity flavor (`$state`, `$state.raw`, `$derived`, `$derived.by`)
233
304
  * when this variable is initialized with a value-producing rune.
@@ -246,6 +317,11 @@ export class Declaration {
246
317
  return this.deprecated_message !== undefined;
247
318
  }
248
319
 
320
+ // presence, not truthiness — a bare `@internal` (no message text) arrives as `''`
321
+ get is_internal(): boolean {
322
+ return this.internal_message !== undefined;
323
+ }
324
+
249
325
  get has_documentation(): boolean {
250
326
  return !!this.doc_comment;
251
327
  }
@@ -3,8 +3,8 @@
3
3
  import type { ProjectStatsSnapshot } from './project_stats.ts';
4
4
 
5
5
  export const project_stats_data: ProjectStatsSnapshot = {
6
- generated_at: '2026-08-11T15:59:58.575Z',
7
- end_date: '2026-08-11',
6
+ generated_at: '2026-08-31T17:42:38.471Z',
7
+ end_date: '2026-08-31',
8
8
  projects: [
9
9
  {
10
10
  name: 'fuz_app',
@@ -14,7 +14,8 @@ export const project_stats_data: ProjectStatsSnapshot = {
14
14
  6, 5, 1, 18, 19, 30, 9, 4, 3, 1, 0, 0, 0, 0, 0, 0, 0, 5, 6, 0, 2, 11, 7, 7, 0, 6, 4, 4, 6, 2,
15
15
  0, 0, 0, 0, 0, 9, 3, 13, 4, 11, 2, 1, 4, 4, 1, 0, 1, 0, 5, 0, 0, 0, 2, 7, 6, 10, 4, 0, 0, 0,
16
16
  6, 5, 5, 6, 12, 4, 1, 1, 0, 1, 0, 0, 0, 7, 1, 0, 1, 3, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2,
17
- 0, 1, 0, 1, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 1, 12, 6, 0, 0, 0
17
+ 0, 1, 0, 1, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 1, 12, 6, 0, 0, 2, 0, 0, 0, 0, 0, 0, 2, 0, 0,
18
+ 0, 0, 0, 0, 0, 0, 1, 0, 9, 6, 0
18
19
  ]
19
20
  },
20
21
  {
@@ -48,7 +49,8 @@ export const project_stats_data: ProjectStatsSnapshot = {
48
49
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
49
50
  1, 3, 7, 0, 0, 0, 1, 2, 2, 2, 0, 1, 1, 1, 1, 2, 0, 6, 3, 1, 0, 0, 0, 5, 0, 2, 0, 0, 0, 0, 0,
50
51
  2, 1, 0, 0, 0, 4, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
51
- 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
52
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
53
+ 0, 0, 0
52
54
  ]
53
55
  },
54
56
  {
@@ -85,7 +87,8 @@ export const project_stats_data: ProjectStatsSnapshot = {
85
87
  0, 2, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
86
88
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 12, 8, 3, 0, 0, 3, 0, 2, 3, 3, 0, 3, 7, 8,
87
89
  3, 0, 4, 0, 1, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 8, 10, 0, 2, 2, 0, 3, 0, 3, 0, 0,
88
- 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1
90
+ 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 10, 0,
91
+ 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 2
89
92
  ]
90
93
  },
91
94
  {
@@ -154,8 +157,8 @@ export const project_stats_data: ProjectStatsSnapshot = {
154
157
  0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
155
158
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 2, 0, 0, 0, 0, 1, 3, 0,
156
159
  0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 2, 0, 2, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
157
- 0, 3, 0, 0, 0, 1, 0, 0, 3, 1, 0, 0, 0, 2, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
158
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
160
+ 0, 3, 0, 0, 0, 1, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
161
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
159
162
  ]
160
163
  },
161
164
  {
@@ -185,8 +188,9 @@ export const project_stats_data: ProjectStatsSnapshot = {
185
188
  0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1,
186
189
  0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0,
187
190
  0, 0, 1, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 1, 0, 2, 2, 0, 1, 0, 2, 3, 0, 2, 0, 3, 0, 0, 0, 0, 0,
188
- 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 10, 0, 1, 0, 0, 0, 0, 0, 1,
189
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0
191
+ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
192
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
193
+ 0, 0, 0, 0, 0, 0, 0, 0, 0
190
194
  ]
191
195
  },
192
196
  {
@@ -227,7 +231,7 @@ export const project_stats_data: ProjectStatsSnapshot = {
227
231
  0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 4, 0, 0, 0, 1, 1, 0, 3, 0, 0, 0,
228
232
  0, 1, 2, 0, 4, 4, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4,
229
233
  5, 0, 0, 0, 4, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
230
- 0
234
+ 2, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
231
235
  ]
232
236
  },
233
237
  {
@@ -266,7 +270,8 @@ export const project_stats_data: ProjectStatsSnapshot = {
266
270
  0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
267
271
  0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 1, 0, 2, 0, 0, 1, 0,
268
272
  2, 3, 0, 2, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0,
269
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
273
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
274
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
270
275
  ]
271
276
  },
272
277
  {
@@ -305,8 +310,8 @@ export const project_stats_data: ProjectStatsSnapshot = {
305
310
  0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 3, 1, 0, 0, 0, 0, 0, 2, 3, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0,
306
311
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 12, 0, 1,
307
312
  0, 3, 3, 0, 5, 0, 0, 1, 0, 2, 4, 1, 4, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
308
- 2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2,
309
- 0, 0, 0, 0, 0, 0, 0, 0, 0
313
+ 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
314
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
310
315
  ]
311
316
  },
312
317
  {
@@ -315,7 +320,8 @@ export const project_stats_data: ProjectStatsSnapshot = {
315
320
  daily_counts: [
316
321
  11, 8, 0, 1, 0, 5, 2, 4, 2, 0, 1, 0, 2, 13, 5, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
317
322
  0, 1, 0, 0, 0, 8, 1, 1, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
318
- 0, 0, 0, 1, 4, 2, 0, 2, 3, 1, 4, 13, 8, 2
323
+ 0, 0, 0, 1, 4, 2, 0, 2, 3, 1, 4, 13, 8, 7, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
324
+ 0, 0, 0
319
325
  ]
320
326
  },
321
327
  {
@@ -366,7 +372,7 @@ export const project_stats_data: ProjectStatsSnapshot = {
366
372
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 5, 1, 0, 0, 0, 0, 1, 3, 2, 0, 0, 0, 9, 0, 1, 0, 5,
367
373
  5, 4, 3, 0, 0, 1, 0, 1, 2, 0, 2, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 2, 0,
368
374
  0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0,
369
- 0, 0, 1, 0, 0, 0, 0
375
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
370
376
  ]
371
377
  },
372
378
  {
@@ -455,8 +461,8 @@ export const project_stats_data: ProjectStatsSnapshot = {
455
461
  2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 3, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
456
462
  0, 0, 0, 0, 0, 0, 2, 1, 0, 0, 1, 3, 1, 0, 0, 1, 0, 0, 0, 0, 0, 5, 5, 0, 0, 2, 8, 2, 2, 0, 0,
457
463
  0, 0, 1, 2, 1, 3, 1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0,
458
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0,
459
- 0, 0
464
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
465
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
460
466
  ]
461
467
  },
462
468
  {
@@ -465,7 +471,8 @@ export const project_stats_data: ProjectStatsSnapshot = {
465
471
  daily_counts: [
466
472
  3, 11, 8, 16, 12, 14, 6, 14, 11, 4, 10, 21, 26, 11, 15, 22, 20, 13, 28, 16, 32, 19, 22, 27,
467
473
  28, 4, 28, 27, 16, 12, 31, 20, 19, 24, 17, 13, 16, 13, 15, 13, 16, 17, 8, 13, 1, 14, 18, 5,
468
- 8, 30, 9, 4, 23, 9, 11, 7, 9, 6, 15, 17, 6
474
+ 8, 30, 9, 4, 23, 9, 11, 7, 9, 6, 15, 17, 12, 13, 19, 23, 17, 22, 11, 19, 16, 11, 11, 4, 13,
475
+ 8, 6, 10, 9, 11, 7, 13, 0
469
476
  ]
470
477
  }
471
478
  ]