dispersa 0.4.2 → 1.0.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.
Files changed (62) hide show
  1. package/README.md +73 -39
  2. package/dist/android-CRDfSB3_.d.cts +126 -0
  3. package/dist/android-DANJjjPO.d.ts +126 -0
  4. package/dist/builders.cjs +220 -64
  5. package/dist/builders.cjs.map +1 -1
  6. package/dist/builders.d.cts +15 -13
  7. package/dist/builders.d.ts +15 -13
  8. package/dist/builders.js +220 -64
  9. package/dist/builders.js.map +1 -1
  10. package/dist/cli/cli.js +120 -7
  11. package/dist/cli/cli.js.map +1 -1
  12. package/dist/cli/config.d.ts +321 -0
  13. package/dist/cli/config.js.map +1 -1
  14. package/dist/cli/index.js +119 -7
  15. package/dist/cli/index.js.map +1 -1
  16. package/dist/dispersa-BC1kDF5u.d.ts +118 -0
  17. package/dist/dispersa-DL3J_Pmz.d.cts +118 -0
  18. package/dist/errors-qT4sJgSA.d.cts +104 -0
  19. package/dist/errors-qT4sJgSA.d.ts +104 -0
  20. package/dist/errors.cjs.map +1 -1
  21. package/dist/errors.d.cts +1 -83
  22. package/dist/errors.d.ts +1 -83
  23. package/dist/errors.js.map +1 -1
  24. package/dist/filters.cjs.map +1 -1
  25. package/dist/filters.d.cts +2 -2
  26. package/dist/filters.d.ts +2 -2
  27. package/dist/filters.js.map +1 -1
  28. package/dist/{index-CNT2Meyf.d.cts → index-Dajm5rvM.d.ts} +311 -132
  29. package/dist/{index-CqdaN3X0.d.ts → index-De6SjZYH.d.cts} +311 -132
  30. package/dist/index.cjs +813 -355
  31. package/dist/index.cjs.map +1 -1
  32. package/dist/index.d.cts +8 -329
  33. package/dist/index.d.ts +8 -329
  34. package/dist/index.js +807 -355
  35. package/dist/index.js.map +1 -1
  36. package/dist/lint.cjs +1017 -0
  37. package/dist/lint.cjs.map +1 -0
  38. package/dist/lint.d.cts +463 -0
  39. package/dist/lint.d.ts +463 -0
  40. package/dist/lint.js +997 -0
  41. package/dist/lint.js.map +1 -0
  42. package/dist/preprocessors.d.cts +2 -2
  43. package/dist/preprocessors.d.ts +2 -2
  44. package/dist/renderers.cjs.map +1 -1
  45. package/dist/renderers.d.cts +7 -6
  46. package/dist/renderers.d.ts +7 -6
  47. package/dist/renderers.js.map +1 -1
  48. package/dist/transforms.cjs +0 -12
  49. package/dist/transforms.cjs.map +1 -1
  50. package/dist/transforms.d.cts +3 -7
  51. package/dist/transforms.d.ts +3 -7
  52. package/dist/transforms.js +1 -12
  53. package/dist/transforms.js.map +1 -1
  54. package/dist/{types-CZb19kiq.d.ts → types-8MLtztK3.d.ts} +56 -1
  55. package/dist/{types-CussyWwe.d.cts → types-BHBHRm0a.d.cts} +56 -1
  56. package/dist/{types-BAv39mum.d.cts → types-BltzwVYK.d.cts} +1 -1
  57. package/dist/{types-DWKq-eJj.d.cts → types-CAdUV-fa.d.cts} +1 -1
  58. package/dist/{types-CzHa7YkW.d.ts → types-DztXKlka.d.ts} +1 -1
  59. package/dist/{types-Bc0kA7De.d.ts → types-TQHV1MrY.d.cts} +19 -1
  60. package/dist/{types-Bc0kA7De.d.cts → types-TQHV1MrY.d.ts} +19 -1
  61. package/dist/{types-BzNcG-rI.d.ts → types-ebxDimRz.d.ts} +1 -1
  62. package/package.json +11 -1
package/README.md CHANGED
@@ -8,6 +8,7 @@ A TypeScript build system for processing [DTCG 2025.10](https://www.designtokens
8
8
  - **Multiple outputs** -- CSS custom properties, JSON, JS/TS modules
9
9
  - **Extensible pipeline** -- custom preprocessors, filters, transforms, and renderers
10
10
  - **Schema validation** -- AJV runtime validation with schema-generated TypeScript types
11
+ - **Linting** -- Plugin-based lint rules for design token validation
11
12
  - **In-memory mode** -- use without the filesystem for build tools, APIs, and testing
12
13
  - **CLI** -- config-first workflow with auto-discovery
13
14
 
@@ -17,6 +18,23 @@ A TypeScript build system for processing [DTCG 2025.10](https://www.designtokens
17
18
 
18
19
  **Composite types:** `shadow`, `typography`, `border`, `strokeStyle`, `transition`, `gradient`
19
20
 
21
+ ## Linting
22
+
23
+ Dispersa includes a plugin-based linting system to validate design tokens against semantic rules. Linting can run standalone or as part of the build pipeline.
24
+
25
+ ```typescript
26
+ import { lint } from 'dispersa'
27
+ import { dispersaPlugin, recommendedConfig } from 'dispersa/lint'
28
+
29
+ const result = await lint({
30
+ resolver: './tokens.resolver.json',
31
+ ...recommendedConfig,
32
+ })
33
+ console.log(`Found ${result.errorCount} errors, ${result.warningCount} warnings`)
34
+ ```
35
+
36
+ Built-in rules include `require-description`, `naming-convention`, `no-deprecated-usage`, `no-duplicate-values`, and `path-schema`. Create custom rules with the `createRule()` factory or build reusable plugins.
37
+
20
38
  ## Getting started
21
39
 
22
40
  ### New project
@@ -39,8 +57,8 @@ Define tokens inline and build CSS -- no files needed:
39
57
 
40
58
  ```typescript
41
59
  import type { ResolverDocument } from 'dispersa'
42
- import { Dispersa, css } from 'dispersa'
43
- import { colorToHex, nameKebabCase } from 'dispersa/transforms'
60
+ import { build, css } from 'dispersa'
61
+ import { colorToHex } from 'dispersa/transforms'
44
62
 
45
63
  const resolver: ResolverDocument = {
46
64
  version: '2025.10',
@@ -100,15 +118,17 @@ const resolver: ResolverDocument = {
100
118
  resolutionOrder: [{ $ref: '#/sets/base' }, { $ref: '#/modifiers/theme' }],
101
119
  }
102
120
 
103
- const dispersa = new Dispersa({ resolver })
121
+ import { build, css } from 'dispersa'
122
+ import { colorToHex } from 'dispersa/transforms'
104
123
 
105
- const result = await dispersa.build({
124
+ const result = await build({
125
+ resolver,
106
126
  outputs: [
107
127
  css({
108
128
  name: 'css',
109
129
  preset: 'bundle',
110
130
  selector: ':root',
111
- transforms: [nameKebabCase(), colorToHex()],
131
+ transforms: [colorToHex()],
112
132
  }),
113
133
  ],
114
134
  })
@@ -275,7 +295,6 @@ Import from `dispersa/transforms`. All transforms are factory functions that ret
275
295
  | `nameSnakeCase()` | `color_brand_primary` |
276
296
  | `namePascalCase()` | `ColorBrandPrimary` |
277
297
  | `nameConstantCase()` | `COLOR_BRAND_PRIMARY` |
278
- | `nameCssVar()` | `--color-brand-primary` |
279
298
  | `namePrefix(prefix)` | `ds-color-brand-primary` |
280
299
  | `nameSuffix(suffix)` | `color-brand-primary-token` |
281
300
 
@@ -306,7 +325,7 @@ css({
306
325
  file: 'colors.css',
307
326
  preset: 'bundle',
308
327
  filters: [byType('color')],
309
- transforms: [nameKebabCase(), colorToHex()],
328
+ transforms: [colorToHex()],
310
329
  })
311
330
 
312
331
  css({
@@ -314,7 +333,7 @@ css({
314
333
  file: 'semantic.css',
315
334
  preset: 'modifier',
316
335
  filters: [isAlias()],
317
- transforms: [nameKebabCase(), colorToHex()],
336
+ transforms: [colorToHex()],
318
337
  })
319
338
  ```
320
339
 
@@ -569,8 +588,8 @@ Dispersa can run entirely without the filesystem. Pass a `ResolverDocument` obje
569
588
 
570
589
  ```typescript
571
590
  import type { ResolverDocument } from 'dispersa'
572
- import { Dispersa, css } from 'dispersa'
573
- import { colorToHex, nameKebabCase } from 'dispersa/transforms'
591
+ import { build, css } from 'dispersa'
592
+ import { colorToHex } from 'dispersa/transforms'
574
593
 
575
594
  const resolver: ResolverDocument = {
576
595
  version: '2025.10',
@@ -591,15 +610,14 @@ const resolver: ResolverDocument = {
591
610
  resolutionOrder: [{ $ref: '#/sets/base' }],
592
611
  }
593
612
 
594
- const dispersa = new Dispersa({ resolver })
595
-
596
- const result = await dispersa.build({
613
+ const result = await build({
614
+ resolver,
597
615
  outputs: [
598
616
  css({
599
617
  name: 'css',
600
618
  preset: 'bundle',
601
619
  selector: ':root',
602
- transforms: [nameKebabCase(), colorToHex()],
620
+ transforms: [colorToHex()],
603
621
  }),
604
622
  ],
605
623
  })
@@ -710,7 +728,7 @@ The CLI auto-discovers config files named `dispersa.config.(ts|js|mts|mjs|cts|cj
710
728
  // dispersa.config.ts
711
729
  import { defineConfig } from 'dispersa/config'
712
730
  import { css, json } from 'dispersa'
713
- import { colorToHex, nameKebabCase } from 'dispersa/transforms'
731
+ import { colorToHex } from 'dispersa/transforms'
714
732
 
715
733
  export default defineConfig({
716
734
  resolver: './tokens.resolver.json',
@@ -721,7 +739,7 @@ export default defineConfig({
721
739
  file: 'tokens.css',
722
740
  preset: 'bundle',
723
741
  selector: ':root',
724
- transforms: [nameKebabCase(), colorToHex()],
742
+ transforms: [colorToHex()],
725
743
  }),
726
744
  json({
727
745
  name: 'json',
@@ -735,43 +753,59 @@ export default defineConfig({
735
753
 
736
754
  ## API reference
737
755
 
738
- ### `Dispersa` class
756
+ ### Core functions
757
+
758
+ Dispersa provides standalone functions for all operations:
739
759
 
740
760
  ```typescript
741
- const dispersa = new Dispersa(options?: DispersaOptions)
761
+ import {
762
+ build,
763
+ buildOrThrow,
764
+ buildPermutation,
765
+ resolveTokens,
766
+ lint,
767
+ resolveAllPermutations,
768
+ generateTypes,
769
+ } from 'dispersa'
742
770
  ```
743
771
 
744
- **Constructor options:**
745
-
746
- | Option | Type | Description |
747
- | ------------ | --------------------------------------- | ------------------------------------------------------ |
748
- | `resolver` | `string \| ResolverDocument` | Default resolver (file path or inline object) |
749
- | `buildPath` | `string` | Default output directory |
750
- | `validation` | `{ mode?: 'error' \| 'warn' \| 'off' }` | Validation behavior (`'warn'` logs via `console.warn`) |
751
-
752
- **Methods:**
753
-
754
- | Method | Description |
772
+ | Function | Description |
755
773
  | ------------------------------------------- | ----------------------------------------------------- |
756
774
  | `build(config)` | Build tokens. Returns `BuildResult` (never throws). |
757
775
  | `buildOrThrow(config)` | Build tokens. Throws on failure. |
758
776
  | `buildPermutation(config, modifierInputs?)` | Build a single permutation. |
759
777
  | `resolveTokens(resolver, modifierInputs?)` | Resolve tokens for one permutation without rendering. |
778
+ | `lint(options)` | Run lint rules on resolved tokens. |
760
779
  | `resolveAllPermutations(resolver)` | Resolve tokens for every permutation. |
761
780
  | `generateTypes(tokens, fileName, options?)` | Generate a `.d.ts` file from resolved tokens. |
762
781
 
782
+ ### BuildConfig
783
+
784
+ When calling `build()` or `buildOrThrow()`, pass a `BuildConfig` object:
785
+
786
+ | Option | Type | Description |
787
+ | ------------ | --------------------------------------- | ------------------------------------- |
788
+ | `resolver` | `string \| ResolverDocument` | Resolver (file path or inline object) |
789
+ | `buildPath` | `string` | Output directory |
790
+ | `outputs` | `OutputConfig[]` | Array of output configurations |
791
+ | `validation` | `{ mode?: 'error' \| 'warn' \| 'off' }` | Validation behavior |
792
+ | `filters` | `Filter[]` | Global filters |
793
+ | `transforms` | `Transform[]` | Global transforms |
794
+ | `lint` | `LintBuildConfig` | Lint configuration |
795
+
763
796
  ### Subpath exports
764
797
 
765
- | Export | Description |
766
- | ------------------------ | ---------------------------------------------------------------------------- |
767
- | `dispersa` | `Dispersa` class, builder functions (`css`, `json`, `js`, `tailwind`), types |
768
- | `dispersa/transforms` | Built-in transform factories |
769
- | `dispersa/filters` | Built-in filter factories |
770
- | `dispersa/builders` | Output builder functions |
771
- | `dispersa/renderers` | Renderer types, `defineRenderer`, and `outputTree` helper |
772
- | `dispersa/preprocessors` | Preprocessor type |
773
- | `dispersa/errors` | Error classes (`DispersaError`, `TokenReferenceError`, etc.) |
774
- | `dispersa/config` | `defineConfig` helper for CLI config files |
798
+ | Export | Description |
799
+ | ------------------------ | ---------------------------------------------------------------------- |
800
+ | `dispersa` | Core functions (`build`, `lint`, etc.), builder functions, types |
801
+ | `dispersa/transforms` | Built-in transform factories |
802
+ | `dispersa/filters` | Built-in filter factories |
803
+ | `dispersa/builders` | Output builder functions |
804
+ | `dispersa/renderers` | Renderer types, `defineRenderer`, and `outputTree` helper |
805
+ | `dispersa/preprocessors` | Preprocessor type |
806
+ | `dispersa/errors` | Error classes (`DispersaError`, `TokenReferenceError`, etc.) |
807
+ | `dispersa/config` | `defineConfig` helper for CLI config files |
808
+ | `dispersa/lint` | Linting system: `LintRunner`, built-in rules, `createRule`, formatters |
775
809
 
776
810
  Everything outside these entry points is internal and not a stable API contract.
777
811
 
@@ -0,0 +1,126 @@
1
+ import { S as SelectorFunction, M as MediaQueryFunction } from './index-De6SjZYH.cjs';
2
+
3
+ /**
4
+ * @license MIT
5
+ * Copyright (c) 2025-present Dispersa Contributors
6
+ *
7
+ * This source code is licensed under the MIT license found in the
8
+ * LICENSE file in the root directory of this source tree.
9
+ */
10
+
11
+ /**
12
+ * Options for Tailwind CSS v4 renderer
13
+ *
14
+ * Controls how tokens are converted to Tailwind v4 @theme CSS variables.
15
+ *
16
+ * @example Bundle with dark mode overrides
17
+ * ```typescript
18
+ * tailwind({
19
+ * name: 'tailwind',
20
+ * file: 'theme.css',
21
+ * preset: 'bundle',
22
+ * selector: (modifier, context, isBase) => {
23
+ * if (isBase) return ':root'
24
+ * return `[data-${modifier}="${context}"]`
25
+ * },
26
+ * })
27
+ * ```
28
+ */
29
+ type TailwindRendererOptions = {
30
+ preset?: 'bundle' | 'standalone';
31
+ includeImport?: boolean;
32
+ namespace?: string;
33
+ minify?: boolean;
34
+ selector?: string | SelectorFunction;
35
+ mediaQuery?: string | MediaQueryFunction;
36
+ };
37
+
38
+ /**
39
+ * @license MIT
40
+ * Copyright (c) 2025-present Dispersa Contributors
41
+ *
42
+ * This source code is licensed under the MIT license found in the
43
+ * LICENSE file in the root directory of this source tree.
44
+ */
45
+
46
+ /**
47
+ * Options for iOS/SwiftUI renderer
48
+ */
49
+ type IosRendererOptions = {
50
+ preset?: 'standalone';
51
+ accessLevel?: 'public' | 'internal';
52
+ /**
53
+ * Output structure:
54
+ * - `'enum'` — nested enums inside a single root enum
55
+ * - `'grouped'` — namespace enum with separate extensions per token group
56
+ */
57
+ structure?: 'enum' | 'grouped';
58
+ enumName?: string;
59
+ /** Namespace enum name used in grouped mode (default: 'DesignTokens') */
60
+ extensionNamespace?: string;
61
+ colorSpace?: 'sRGB' | 'displayP3';
62
+ /**
63
+ * Target Swift language version.
64
+ * - `'5.9'` (default) — standard static let declarations
65
+ * - `'6.0'` — adds `nonisolated(unsafe)` to static properties for
66
+ * Swift 6 strict concurrency compliance
67
+ */
68
+ swiftVersion?: '5.9' | '6.0';
69
+ /** Number of spaces per indentation level (default 4) */
70
+ indent?: number;
71
+ /** Add @frozen annotation to enums and structs for ABI stability (default false) */
72
+ frozen?: boolean;
73
+ };
74
+
75
+ /**
76
+ * @license MIT
77
+ * Copyright (c) 2025-present Dispersa Contributors
78
+ *
79
+ * This source code is licensed under the MIT license found in the
80
+ * LICENSE file in the root directory of this source tree.
81
+ */
82
+
83
+ /**
84
+ * Options for Android/Jetpack Compose renderer
85
+ *
86
+ * Note: `packageName` is marked optional for type compatibility with the Renderer
87
+ * generic, but is validated as required at runtime in the renderer's format() method.
88
+ *
89
+ * @experimental This type is experimental. Properties and behavior may change.
90
+ */
91
+ type AndroidRendererOptions = {
92
+ preset?: 'standalone' | 'bundle';
93
+ packageName?: string;
94
+ objectName?: string;
95
+ /**
96
+ * Color output format for Kotlin Color initializers.
97
+ * - `'argb_hex'` (default) — `Color(0xAARRGGBB)` hex literal
98
+ * - `'argb_float'` — `Color(r, g, b, a)` float components
99
+ *
100
+ * Legacy aliases: `'argb8'` maps to `'argb_hex'`, `'argb_floats'` maps to `'argb_float'`.
101
+ */
102
+ colorFormat?: 'argb_hex' | 'argb_float' | 'argb8' | 'argb_floats';
103
+ /**
104
+ * Color space for generated Color values.
105
+ * - `'sRGB'` (default) — standard sRGB color space
106
+ * - `'displayP3'` — Display P3 wide gamut via `ColorSpaces.DisplayP3`
107
+ */
108
+ colorSpace?: 'sRGB' | 'displayP3';
109
+ /**
110
+ * Structure mode for token organization.
111
+ * - `'nested'` (default) — mirror token path hierarchy as nested objects
112
+ * - `'flat'` — group tokens by $type into semantic sub-objects (Colors, Spacing, etc.)
113
+ */
114
+ structure?: 'nested' | 'flat';
115
+ /**
116
+ * Kotlin visibility modifier for the generated object and its members.
117
+ * - `undefined` (default) — no explicit modifier, which means `public` in Kotlin
118
+ * - `'public'` — explicit `public object` / `public val`
119
+ * - `'internal'` — `internal object` / `internal val` (useful for KMP / multi-module)
120
+ */
121
+ visibility?: 'public' | 'internal';
122
+ /** Number of spaces per indentation level (default 4) */
123
+ indent?: number;
124
+ };
125
+
126
+ export type { AndroidRendererOptions as A, IosRendererOptions as I, TailwindRendererOptions as T };
@@ -0,0 +1,126 @@
1
+ import { S as SelectorFunction, M as MediaQueryFunction } from './index-Dajm5rvM.js';
2
+
3
+ /**
4
+ * @license MIT
5
+ * Copyright (c) 2025-present Dispersa Contributors
6
+ *
7
+ * This source code is licensed under the MIT license found in the
8
+ * LICENSE file in the root directory of this source tree.
9
+ */
10
+
11
+ /**
12
+ * Options for Tailwind CSS v4 renderer
13
+ *
14
+ * Controls how tokens are converted to Tailwind v4 @theme CSS variables.
15
+ *
16
+ * @example Bundle with dark mode overrides
17
+ * ```typescript
18
+ * tailwind({
19
+ * name: 'tailwind',
20
+ * file: 'theme.css',
21
+ * preset: 'bundle',
22
+ * selector: (modifier, context, isBase) => {
23
+ * if (isBase) return ':root'
24
+ * return `[data-${modifier}="${context}"]`
25
+ * },
26
+ * })
27
+ * ```
28
+ */
29
+ type TailwindRendererOptions = {
30
+ preset?: 'bundle' | 'standalone';
31
+ includeImport?: boolean;
32
+ namespace?: string;
33
+ minify?: boolean;
34
+ selector?: string | SelectorFunction;
35
+ mediaQuery?: string | MediaQueryFunction;
36
+ };
37
+
38
+ /**
39
+ * @license MIT
40
+ * Copyright (c) 2025-present Dispersa Contributors
41
+ *
42
+ * This source code is licensed under the MIT license found in the
43
+ * LICENSE file in the root directory of this source tree.
44
+ */
45
+
46
+ /**
47
+ * Options for iOS/SwiftUI renderer
48
+ */
49
+ type IosRendererOptions = {
50
+ preset?: 'standalone';
51
+ accessLevel?: 'public' | 'internal';
52
+ /**
53
+ * Output structure:
54
+ * - `'enum'` — nested enums inside a single root enum
55
+ * - `'grouped'` — namespace enum with separate extensions per token group
56
+ */
57
+ structure?: 'enum' | 'grouped';
58
+ enumName?: string;
59
+ /** Namespace enum name used in grouped mode (default: 'DesignTokens') */
60
+ extensionNamespace?: string;
61
+ colorSpace?: 'sRGB' | 'displayP3';
62
+ /**
63
+ * Target Swift language version.
64
+ * - `'5.9'` (default) — standard static let declarations
65
+ * - `'6.0'` — adds `nonisolated(unsafe)` to static properties for
66
+ * Swift 6 strict concurrency compliance
67
+ */
68
+ swiftVersion?: '5.9' | '6.0';
69
+ /** Number of spaces per indentation level (default 4) */
70
+ indent?: number;
71
+ /** Add @frozen annotation to enums and structs for ABI stability (default false) */
72
+ frozen?: boolean;
73
+ };
74
+
75
+ /**
76
+ * @license MIT
77
+ * Copyright (c) 2025-present Dispersa Contributors
78
+ *
79
+ * This source code is licensed under the MIT license found in the
80
+ * LICENSE file in the root directory of this source tree.
81
+ */
82
+
83
+ /**
84
+ * Options for Android/Jetpack Compose renderer
85
+ *
86
+ * Note: `packageName` is marked optional for type compatibility with the Renderer
87
+ * generic, but is validated as required at runtime in the renderer's format() method.
88
+ *
89
+ * @experimental This type is experimental. Properties and behavior may change.
90
+ */
91
+ type AndroidRendererOptions = {
92
+ preset?: 'standalone' | 'bundle';
93
+ packageName?: string;
94
+ objectName?: string;
95
+ /**
96
+ * Color output format for Kotlin Color initializers.
97
+ * - `'argb_hex'` (default) — `Color(0xAARRGGBB)` hex literal
98
+ * - `'argb_float'` — `Color(r, g, b, a)` float components
99
+ *
100
+ * Legacy aliases: `'argb8'` maps to `'argb_hex'`, `'argb_floats'` maps to `'argb_float'`.
101
+ */
102
+ colorFormat?: 'argb_hex' | 'argb_float' | 'argb8' | 'argb_floats';
103
+ /**
104
+ * Color space for generated Color values.
105
+ * - `'sRGB'` (default) — standard sRGB color space
106
+ * - `'displayP3'` — Display P3 wide gamut via `ColorSpaces.DisplayP3`
107
+ */
108
+ colorSpace?: 'sRGB' | 'displayP3';
109
+ /**
110
+ * Structure mode for token organization.
111
+ * - `'nested'` (default) — mirror token path hierarchy as nested objects
112
+ * - `'flat'` — group tokens by $type into semantic sub-objects (Colors, Spacing, etc.)
113
+ */
114
+ structure?: 'nested' | 'flat';
115
+ /**
116
+ * Kotlin visibility modifier for the generated object and its members.
117
+ * - `undefined` (default) — no explicit modifier, which means `public` in Kotlin
118
+ * - `'public'` — explicit `public object` / `public val`
119
+ * - `'internal'` — `internal object` / `internal val` (useful for KMP / multi-module)
120
+ */
121
+ visibility?: 'public' | 'internal';
122
+ /** Number of spaces per indentation level (default 4) */
123
+ indent?: number;
124
+ };
125
+
126
+ export type { AndroidRendererOptions as A, IosRendererOptions as I, TailwindRendererOptions as T };