nuvox 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CONTRACT.md ADDED
@@ -0,0 +1,255 @@
1
+ # Nuvox Foundation — Contract
2
+
3
+ This is the rulebook for building each future component on top of this
4
+ base. It exists so decisions get made once, here, instead of once per
5
+ component. Every rule below is backed by a specific bug found in the old
6
+ codebase — see the parenthetical.
7
+
8
+ ## 1. Size scale
9
+ Import `Size` from `src/core/types.ts`. Don't declare a component-local
10
+ size union. If a component genuinely needs a wider scale (Modal + "full",
11
+ Avatar + "2xl"), extend the shared type explicitly:
12
+ ```ts
13
+ export type ModalSize = Size | "full"
14
+ ```
15
+ (Old bug: 4 different, undocumented size scales across 41 components.)
16
+
17
+ ## 2. Base props
18
+ Every component's prop interface extends `BaseComponentProps`
19
+ (`className`, `style`, `theme`). Only add `color` / `radius` as
20
+ component-specific overrides if the component genuinely needs one —
21
+ but when you do, use the same shape every other component uses.
22
+ (Old bug: `color` on 6/41 components, `radius` on 2/41, no rule for
23
+ which.)
24
+
25
+ ## 3. Nullish coalescing only
26
+ Use `??` for every prop default, never `||`. `||` silently discards a
27
+ valid `false`/`0`/`""`.
28
+ (Old bug: 36 files used `??`, 5 used `||`, inconsistently.)
29
+
30
+ ## 4. Ref forwarding is the default, not a judgment call
31
+ Every component uses `forwardRef`. See `src/react/Button.tsx` as the
32
+ template. The only exemption is a component with no focusable or
33
+ interactive native element at all (`Divider`, `NuvoxProvider`,
34
+ `ToastProvider` — it renders a variable-length list of toasts inside
35
+ a portal, with no single focusable element to forward to — other
36
+ pure layout/context wrappers) — that's a concrete, checkable exception,
37
+ not a "forward it if it seems worth it" judgment call. Anything with a
38
+ real DOM node a consumer might plausibly focus, measure, or scroll
39
+ forwards its ref, full stop.
40
+ (Old bug: 1 of 41 components forwarded a ref — and the failure mode
41
+ was exactly "judgment calls made independently, 41 times." A vague
42
+ exception clause reopens that same door.)
43
+
44
+ ## 5. Theme/accent override, not theme/accent logic
45
+ A component with `theme?: string` and/or `color?: string` props
46
+ (both from `BaseComponentProps`) wraps its output with
47
+ `withThemeOverride(theme, ...)` and/or `withAccentOverride(color, ...)`
48
+ from `theme-engine/NuvoxProvider`. A component never branches on
49
+ theme or accent identity (`if (theme === "glass")`, `if (color ===
50
+ "teal")`) — it only ever consumes semantic CSS variables. This should
51
+ read naturally whether the theme catalog stays at 3 or grows to 15,
52
+ and whether the accent palette stays at 9 or grows to 30.
53
+ (Old bug: components didn't have this override at all; the doc's
54
+ planned priority rule — component > provider > default — was never
55
+ implemented in code. A second bug, found later: a component accepted
56
+ `theme`/`color` via `BaseComponentProps` and silently ignored both —
57
+ accepting a prop is not the same as applying it; test for the
58
+ override actually taking effect, not just that the prop compiles.)
59
+
60
+ ## 5b. Theme is shape, accent is color — never conflate them
61
+ `ThemeTokens` (see `contract.ts`) has no `color.brand` field, on
62
+ purpose. A theme controls radius, shadow, motion, border treatment,
63
+ and glass/gradient/glow effects — the properties in the doc's own
64
+ original vision of what makes Cyberpunk feel different from Brutalism.
65
+ It does not control the brand accent color at all. Brand color is a
66
+ separate, orthogonal registry (`accents.ts`) that a consumer picks
67
+ independently — "our brand is teal" has to work whether the shape is
68
+ Light, Cyberpunk, or Brutalism, not just the one theme an author
69
+ happened to design it against.
70
+
71
+ This was a real bug, not a hypothetical: `gradient`, `minimalism`, and
72
+ `skeuomorphism` were each authored with their own hardcoded
73
+ `color.brand` scale, which meant every Button rendered pixel-identical
74
+ to Light for anyone who hadn't noticed the hue never differed. It
75
+ compiled fine and passed every completeness check, because
76
+ completeness and distinctness are different properties (see Rule 7's
77
+ note on this) — and it was orthogonality that was actually missing,
78
+ not distinctness.
79
+
80
+ **The one deliberate exception:** `success`/`danger`/`warning`/`info`
81
+ stay theme-defined and are NOT part of the accent system. Their exact
82
+ shade can differ per theme for contrast (dark themes need a lighter
83
+ green than light themes to stay legible), but their meaning — green
84
+ reads as success, red as danger — is not something a consumer should
85
+ be able to accidentally reassign by picking an accent. If you ever
86
+ find yourself wanting `color="success"` to be a valid accent value,
87
+ that's the signal to stop — semantic color and brand color solve
88
+ different problems and must stay separate registries.
89
+
90
+ ## 5c. Text on a solid accent surface uses `--color-brand-onAccent`, never `--color-textInverse`
91
+ This was also a real bug, not a hypothetical: Button's `solid`
92
+ variant, Badge's `solid` variant, and Checkbox's checkmark all paired
93
+ `--color-brand-500` (the accent's fixed color — same value in every
94
+ theme, per Rule 5b) with `--color-textInverse` (a THEME token,
95
+ computed assuming the surface underneath is light or dark depending
96
+ on *that theme*). Those two axes usually agree — until an accent like
97
+ `graphite` (a gray scale, 500: `#525252`) meets `dark` theme
98
+ (`textInverse: #111827`, chosen assuming a *light* surface). Dark
99
+ gray text on a mid-gray background is close to unreadable, and
100
+ nothing in the type system catches it, because both tokens
101
+ individually resolve fine.
102
+
103
+ The fix: `generate-css.ts` computes `--color-brand-onAccent` per
104
+ accent, from that accent's own 500 shade via WCAG relative luminance
105
+ (`tokens/contrast.ts`) — not borrowed from whichever theme happens to
106
+ be active. Any component painting text directly on
107
+ `--color-brand-500` (or another accent step used as a fill) uses
108
+ `--color-brand-onAccent` for that text, full stop.
109
+ `tests/accent-contrast.test.ts` enforces every registered accent's
110
+ computed value clears WCAG AA (4.5:1) against its own 500 shade — a
111
+ new accent that fails this fails CI, not a future bug report.
112
+
113
+ The related, softer case — outline-variant text (`color-mix(in srgb,
114
+ var(--color-brand-600) 65%, var(--color-text) 35%)`) sitting directly
115
+ on a theme's own ambient background rather than a solid accent fill —
116
+ is audited across all 99 theme × accent pairs in
117
+ `tests/outline-text-contrast.test.ts`. That audit surfaced two real
118
+ bugs *in the audit itself* before confirming the actual blend was
119
+ fine: naive hex parsing silently turned `"transparent"` and CSS
120
+ gradient strings into black (bitwise ops coerce `NaN` to `0`), and a
121
+ translucent `rgba()` surface color had its alpha dropped, testing
122
+ against the wrong effective color entirely. Both are fixed in
123
+ `tokens/contrast.ts` (`parseColorWithAlpha`, `compositeOver`,
124
+ `isSolidColor`) — worth knowing about if a future theme introduces
125
+ another non-solid color value, since the same class of silent
126
+ mis-parsing is exactly the kind of bug that doesn't announce itself.
127
+
128
+ ## 6. Portals go through ThemedPortal, never createPortal directly
129
+ Any component that renders outside its own DOM subtree (Popover, Modal,
130
+ Toast, Tooltip, Select, Combobox, DatePicker, Dropdown, ContextMenu,
131
+ Drawer, ColorPicker, PhoneInput, Command, Tour, Kanban's drag layer...)
132
+ imports `ThemedPortal` from `theme-engine/ThemedPortal.tsx` and passes
133
+ it an `anchorRef`. Do not hand-roll the `closest('[data-theme]')` +
134
+ `MutationObserver` fix again — that's exactly how it ended up
135
+ duplicated 12 times and missing from 3 components last time.
136
+
137
+ ## 7. Every new theme is a `.ts` file satisfying `ThemeTokens`
138
+ Author it with `defineTheme()` — an incomplete theme is a compile
139
+ error, not a rendering bug. Register it via `registerTheme()`. Run
140
+ `npm run build:tokens` to regenerate the CSS. Never hand-write a theme
141
+ CSS file directly.
142
+ (Old bug: themes were hand-authored CSS with no completeness check —
143
+ a theme could silently ship missing a variable.)
144
+
145
+ **Completeness is not the same as distinctness.** A theme derived from
146
+ another via spread (the recommended pattern) can be 100% complete —
147
+ every required key present and non-empty — while still being
148
+ structurally indistinguishable from the theme it was derived from (same
149
+ radius, same shadow, same motion). This is exactly what happened before
150
+ `color.brand` was removed from `ThemeTokens` entirely (see Rule 5b):
151
+ `gradient`, `minimalism`, and `skeuomorphism` each shipped with light's
152
+ brand scale untouched, and it passed every check that existed at the
153
+ time, because completeness and distinctness are different properties.
154
+ Rule 5b's fix (moving brand out of themes entirely) closes that
155
+ specific failure mode structurally — a theme literally cannot
156
+ reintroduce a brand color to forget to change, because the field
157
+ doesn't exist. `tests/theme-distinctness.test.ts` is the remaining
158
+ safety net, now checking radius/shadow/motion/border fingerprints
159
+ instead — run it (it's part of `npm test`) for every new theme, and
160
+ don't treat "it compiles and the completeness test passes" as
161
+ equivalent to "it's structurally different from the theme it was
162
+ derived from."
163
+
164
+ ## 7b. Every new accent is a `.ts` file satisfying a full `ColorScale`
165
+ Same pattern as themes, deliberately: create
166
+ `src/tokens/accents/<name>.ts` exporting an `AccentDefinition`
167
+ (`name`, `label`, `scale`), register it via `registerAccent()` in
168
+ `accents.ts`. An incomplete scale throws immediately at registration
169
+ (`assertCompleteScale`), not silently at render time. Accents don't
170
+ need a distinctness test against every theme the way themes do against
171
+ each other — `tests/accent-distinctness.test.ts` only checks accents
172
+ against other accents (no two share a `500` step), since accents and
173
+ themes are different registries serving different purposes.
174
+
175
+ ## 8. Every component ships with tests before it's considered done
176
+ This is a **floor, not a checklist to stop at**. The four tests below
177
+ are the minimum every component needs regardless of what it is; a
178
+ complex component (DataGrid, RichTextEditor, Kanban) needs many more
179
+ tests specific to its own behavior on top of these four, not instead
180
+ of them:
181
+ - One test proving the default (no-props) render is correct
182
+ - One test proving `theme` override scopes correctly (skip if the
183
+ component has no visual output, e.g. a hook)
184
+ - One test proving ref forwarding, if applicable
185
+ - If the component portals: one test proving `ThemedPortal` picked up
186
+ the right theme
187
+ (Old bug: zero tests existed anywhere in the 41-component, ~37k-line
188
+ library.)
189
+
190
+ ## 9. Docs come last, and prefer an existing framework
191
+ Don't build a documentation site until there are components worth
192
+ documenting. Prefer an existing documentation framework (Storybook,
193
+ Nextra, Starlight, or whatever's current when you get there) unless
194
+ there's a specific, compelling reason to build your own — the rule is
195
+ "don't default to building a platform," not "you may never build one."
196
+ (Old bug: three separate documentation apps totaling ~83,500 lines —
197
+ more than twice the size of the entire component library.)
198
+
199
+ ## 10. Public API stability
200
+ Once a prop ships in a released version, it's a promise. Don't rename
201
+ `variant` to `appearance`, don't change what a value means, don't
202
+ change a callback's signature — pick one:
203
+ - **alias** the old name to the new one and deprecate with a console
204
+ warning,
205
+ - or **bump the major version** and document the breaking change.
206
+ Internal architecture (core/, theme-engine/) can be refactored freely;
207
+ anything a consumer imports and passes props to cannot change shape
208
+ silently. This wasn't tested against the old codebase the way the
209
+ other rules were — Nuvox v1 never shipped a public version — but it's
210
+ the rule that protects everything else in this document from being
211
+ undermined the moment real consumers exist.
212
+
213
+ ## 11. Every overlay component meets the same accessibility baseline
214
+ Any component that opens/closes, floats, or portals (Modal, Drawer,
215
+ Popover, Dropdown, Select, Combobox, ContextMenu, Tour, Toast,
216
+ Tooltip...) implements, without exception:
217
+ - `Escape` closes it (where closing is a valid action)
218
+ - Focus is trapped inside while open, and returns to the trigger on
219
+ close
220
+ - Correct ARIA role (`dialog`, `listbox`, `menu`, etc.) and state
221
+ attributes (`aria-expanded`, `aria-modal`, ...)
222
+ - Full keyboard navigation appropriate to the component (arrow keys
223
+ for a listbox, tab cycling in a modal)
224
+ This is the same failure shape as Rule 6 (ThemedPortal) waiting to
225
+ happen — a fix that's easy to duplicate 12 times and forget 3 times if
226
+ each component reimplements it locally. Build focus-trap/escape/ARIA
227
+ handling as a shared hook (e.g. `useOverlayBehavior`) the same way
228
+ `ThemedPortal` centralized the theme fix, rather than reimplementing it
229
+ per component.
230
+
231
+ ## 12. Components compose primitives, they don't reimplement them
232
+ A `Select` doesn't hand-roll its own text field, its own floating
233
+ panel, and its own option-highlighting logic — it composes an `Input`,
234
+ a `Popover`/`ThemedPortal`, and a shared list/option primitive. If two
235
+ components need the same behavior (an editable text field, a floating
236
+ panel, a keyboard-navigable list), that behavior gets built once and
237
+ both components use it. This isn't backed by a specific bug the way
238
+ the other rules are — Nuvox v1 didn't get far enough architecturally
239
+ for this to bite yet — but it's the same principle as Rule 6 (portal
240
+ theming) and Rule 11 (overlay behavior) applied generally: the more
241
+ logic two components share by composition, the fewer places a fix has
242
+ to be duplicated or forgotten later.
243
+
244
+ ---
245
+
246
+ ## Adding a new rule to this document
247
+ Before adding a Rule 13, ask: **does this prevent a class of bugs, or
248
+ just one bug?** "Shared size scale," "theme contract," "ref policy" —
249
+ these prevent a class (N components each making the same kind of
250
+ decision independently). "Buttons should use 14px font" is a design
251
+ token, not an architectural invariant — it belongs in a theme file,
252
+ not here. A contract that grows past what people actually remember and
253
+ apply stops being a contract and becomes a document nobody rereads.
254
+ Keep it to rules that would still make sense five years from now,
255
+ regardless of what the component catalog looks like by then.
package/LICENSE ADDED
@@ -0,0 +1,28 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Nuvox
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
23
+ ---
24
+
25
+ This project includes icons adapted from Lucide (ISC License) and, via
26
+ Lucide, from Feather (MIT License). See THIRD-PARTY-NOTICES.md for the
27
+ full, required notices.
28
+
package/README.md ADDED
@@ -0,0 +1,99 @@
1
+ # Nuvox
2
+
3
+ A framework-agnostic React component library with a themeable,
4
+ token-driven design system. 41 components, 11 visual themes, 9 named
5
+ accent colors (plus support for any raw CSS color), and 492 icons —
6
+ fully typed, accessible, and built on zero runtime dependencies.
7
+
8
+ ## The core idea: theme is shape, color is color
9
+
10
+ A **theme** (`light`, `dark`, `cyberpunk`, `glass`, ...) controls
11
+ radius, shadow, motion, and border treatment. Your **accent color**
12
+ is a completely separate choice — pick a named accent or any raw CSS
13
+ color, and it works identically with every theme:
14
+
15
+ ```tsx
16
+ <NuvoxProvider theme="cyberpunk" accent="teal">
17
+ <Button>Cyberpunk shape, teal brand — not tied to each other</Button>
18
+ </NuvoxProvider>
19
+
20
+ <Button color="#ff6600">A raw hex color works too, no setup</Button>
21
+ ```
22
+
23
+ ## Install
24
+
25
+ ```bash
26
+ npm install nuvox
27
+ ```
28
+
29
+ `react` and `react-dom` are peer dependencies (React 18+) — npm 7+
30
+ installs them automatically if they're missing.
31
+
32
+ ## Quick start
33
+
34
+ ```tsx
35
+ import { NuvoxProvider, Button } from "nuvox/react";
36
+ import "nuvox/themes.css"; // theme + accent CSS variables
37
+ import "nuvox/styles.css"; // component styles
38
+
39
+ function App() {
40
+ return (
41
+ <NuvoxProvider theme="dark" accent="teal">
42
+ <Button>Hello Nuvox</Button>
43
+ </NuvoxProvider>
44
+ );
45
+ }
46
+ ```
47
+
48
+ Both stylesheets are required — `themes.css` defines the CSS
49
+ variables, `styles.css` reads them into visible styles.
50
+
51
+ ## What's in the box
52
+
53
+ - **41 components** across forms (Input, Select, Checkbox, Slider...),
54
+ overlays (Modal, Popover, Dropdown, Drawer...), composite widgets
55
+ (Combobox, DatePicker, CommandPalette...), and navigation
56
+ (Tabs, Accordion, Breadcrumb, Pagination...)
57
+ - **11 themes** (light, dark, glass, dark-glass, minimalism,
58
+ brutalism, neobrutalism, cyberpunk, gradient, material,
59
+ skeuomorphism) — switchable at runtime with no re-render logic
60
+ - **9 named accent colors**, or drop in any raw CSS color with zero
61
+ registration
62
+ - **492 icons**, tree-shakeable, each accepting `size` and `color`
63
+ - Full TypeScript support out of the box — no separate `@types`
64
+ package needed
65
+ - Accessible by default: every overlay component handles focus
66
+ trapping, Escape-to-close, and correct ARIA roles/states
67
+
68
+ ## Switch themes and accents independently
69
+
70
+ ```tsx
71
+ <NuvoxProvider theme="dark" accent="indigo">
72
+ <Button>Ambient dark + indigo</Button>
73
+ <Button theme="glass">Glass shape, still indigo accent</Button>
74
+ <Button color="teal">Dark shape, teal accent instead</Button>
75
+ </NuvoxProvider>
76
+ ```
77
+
78
+ You can also register your own theme or accent from your own code —
79
+ see the [docs site](#docs--examples) for the full guide.
80
+
81
+ ## Docs & examples
82
+
83
+ Every component has a live, interactive example alongside its API
84
+ reference in the docs site:
85
+
86
+ ```bash
87
+ npm run docs:install # first time only
88
+ npm run docs:dev # → http://localhost:3000
89
+ ```
90
+
91
+ - `/docs` — installation and setup
92
+ - `/docs/components` — every component, with live previews
93
+ - `/docs/themes` — the full theme/accent catalog, try them live
94
+ - `/docs/icons` — browse and search all 492 icons
95
+
96
+
97
+ ## License
98
+
99
+ MIT
@@ -0,0 +1,52 @@
1
+ # Third-Party Notices
2
+
3
+ Nuvox's own code is MIT licensed — see [`LICENSE`](./LICENSE). Some icons in
4
+ `src/icons/` are adapted from the [Lucide](https://lucide.dev) icon set,
5
+ which requires its own license notice to travel with the code. That notice
6
+ is reproduced below, unmodified, as required.
7
+
8
+ ---
9
+
10
+ ISC License
11
+
12
+ Copyright (c) 2026 Lucide Icons and Contributors
13
+
14
+ Permission to use, copy, modify, and/or distribute this software for any
15
+ purpose with or without fee is hereby granted, provided that the above
16
+ copyright notice and this permission notice appear in all copies.
17
+
18
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
19
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
20
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
21
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
22
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
23
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
24
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
25
+
26
+ ---
27
+
28
+ The following Lucide icons are derived from the Feather project:
29
+
30
+ airplay, alert-circle, alert-octagon, alert-triangle, aperture, arrow-down-circle, arrow-down-left, arrow-down-right, arrow-down, arrow-left-circle, arrow-left, arrow-right-circle, arrow-right, arrow-up-circle, arrow-up-left, arrow-up-right, arrow-up, at-sign, calendar, cast, check, chevron-down, chevron-left, chevron-right, chevron-up, chevrons-down, chevrons-left, chevrons-right, chevrons-up, circle, clipboard, clock, code, columns, command, compass, corner-down-left, corner-down-right, corner-left-down, corner-left-up, corner-right-down, corner-right-up, corner-up-left, corner-up-right, crosshair, database, divide-circle, divide-square, dollar-sign, download, external-link, feather, frown, hash, headphones, help-circle, info, italic, key, layout, life-buoy, link-2, link, loader, lock, log-in, log-out, maximize, meh, minimize, minimize-2, minus-circle, minus-square, minus, monitor, moon, more-horizontal, more-vertical, move, music, navigation-2, navigation, octagon, pause-circle, percent, plus-circle, plus-square, plus, power, radio, rss, search, server, share, shopping-bag, sidebar, smartphone, smile, square, table-2, tablet, target, terminal, trash-2, trash, triangle, tv, type, upload, x-circle, x-octagon, x-square, x, zoom-in, zoom-out
31
+
32
+ The MIT License (MIT) (for the icons listed above)
33
+
34
+ Copyright (c) 2013-present Cole Bemis
35
+
36
+ Permission is hereby granted, free of charge, to any person obtaining a copy
37
+ of this software and associated documentation files (the "Software"), to deal
38
+ in the Software without restriction, including without limitation the rights
39
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
40
+ copies of the Software, and to permit persons to whom the Software is
41
+ furnished to do so, subject to the following conditions:
42
+
43
+ The above copyright notice and this permission notice shall be included in all
44
+ copies or substantial portions of the Software.
45
+
46
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
47
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
48
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
49
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
50
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
51
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
52
+ SOFTWARE.