@forcir/logo-element 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/README.md +108 -0
- package/package.json +13 -0
- package/src/forcir-brandmark.d.ts +11 -0
- package/src/forcir-brandmark.js +54 -0
- package/src/forcir-logo.d.ts +11 -0
- package/src/forcir-logo.js +83 -0
- package/src/forcir-wordmark.d.ts +11 -0
- package/src/forcir-wordmark.js +55 -0
- package/src/index.d.ts +6 -0
- package/src/index.js +34 -0
- package/src/react.d.ts +30 -0
- package/src/shared-styles.js +27 -0
package/README.md
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# @forcir/logo-element
|
|
2
|
+
|
|
3
|
+
Forcir logo as vanilla JavaScript custom elements. No frameworks, no build step—types are hand-written `.d.ts` files and the package `types` field points at them.
|
|
4
|
+
|
|
5
|
+
## Elements
|
|
6
|
+
|
|
7
|
+
- **`<forcir-logo />`** — Full lockup (brandmark + wordmark)
|
|
8
|
+
- **`<forcir-brandmark />`** — Icon only
|
|
9
|
+
- **`<forcir-wordmark />`** — Wordmark only
|
|
10
|
+
|
|
11
|
+
All use Shadow DOM (open) and support the same attributes and CSS variables.
|
|
12
|
+
|
|
13
|
+
This package is intended for browser environments (including bundlers that target the browser). The elements use `HTMLElement` and Shadow DOM.
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install @forcir/logo-element
|
|
19
|
+
# or
|
|
20
|
+
pnpm add @forcir/logo-element
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Usage
|
|
24
|
+
|
|
25
|
+
### Script tag
|
|
26
|
+
|
|
27
|
+
```html
|
|
28
|
+
<script type="module" src="node_modules/@forcir/logo-element/src/index.js"></script>
|
|
29
|
+
<forcir-logo />
|
|
30
|
+
<forcir-brandmark height="24" />
|
|
31
|
+
<forcir-wordmark />
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### ES module
|
|
35
|
+
|
|
36
|
+
```javascript
|
|
37
|
+
import "@forcir/logo-element";
|
|
38
|
+
// Elements are now registered: <forcir-logo>, <forcir-brandmark>, <forcir-wordmark>
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Or use the classes programmatically:
|
|
42
|
+
|
|
43
|
+
```javascript
|
|
44
|
+
import { ForcirLogoElement, ForcirBrandmarkElement, ForcirWordmarkElement } from "@forcir/logo-element";
|
|
45
|
+
// Use with customElements.define or document.createElement after registration
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Using in React
|
|
49
|
+
|
|
50
|
+
Import the package once (e.g. in your root component or layout) so the custom elements are registered; then use the tags in any component. Your bundler will resolve the ESM package as usual.
|
|
51
|
+
|
|
52
|
+
```jsx
|
|
53
|
+
// In your app entry or layout (once)
|
|
54
|
+
import "@forcir/logo-element";
|
|
55
|
+
|
|
56
|
+
function Header() {
|
|
57
|
+
return (
|
|
58
|
+
<header>
|
|
59
|
+
<a href="/">
|
|
60
|
+
<forcir-logo height={24} />
|
|
61
|
+
</a>
|
|
62
|
+
</header>
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
- **Attributes**: Pass `height` as a number; React will set the attribute on the DOM node. Use `className` and `style` as usual (e.g. `style={{ ["--forcir-logo-foreground"]: "oklch(0.2 0 0)" }}`).
|
|
68
|
+
- **TypeScript**: To type the custom elements in JSX, reference the included declaration so `<forcir-logo />` is valid. In your `tsconfig.json` add to `"include"` (or add a `/// <reference />` in a `.d.ts` file):
|
|
69
|
+
|
|
70
|
+
```json
|
|
71
|
+
"include": ["src", "node_modules/@forcir/logo-element/src/react.d.ts"]
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Your project must have `@types/react` installed. Then you get typed props (e.g. `height?: number`) and refs for the custom elements.
|
|
75
|
+
|
|
76
|
+
## Attributes
|
|
77
|
+
|
|
78
|
+
| Attribute | Type | Default | Description |
|
|
79
|
+
|----------|--------|---------|--------------------------|
|
|
80
|
+
| `height` | number | `18` | SVG height in pixels |
|
|
81
|
+
|
|
82
|
+
Example: `<forcir-brandmark height="24" />`
|
|
83
|
+
|
|
84
|
+
## CSS variables (pass-through)
|
|
85
|
+
|
|
86
|
+
Set these on the custom element or any ancestor so they inherit into the shadow root:
|
|
87
|
+
|
|
88
|
+
| Variable | Description | Used by |
|
|
89
|
+
|----------------------------|--------------------------------|----------------|
|
|
90
|
+
| `--forcir-logo-foreground` | Main logo colour | All variants |
|
|
91
|
+
| `--forcir-logo-muted` | Secondary colour (brandmark) | Brandmark only |
|
|
92
|
+
|
|
93
|
+
Example:
|
|
94
|
+
|
|
95
|
+
```css
|
|
96
|
+
forcir-logo {
|
|
97
|
+
--forcir-logo-foreground: oklch(0.2 0 0);
|
|
98
|
+
--forcir-logo-muted: oklch(0.5 0 0);
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## OKLCH and fallback
|
|
103
|
+
|
|
104
|
+
The component uses OKLCH for default colours when the browser supports it, with an `rgba` fallback when OKLCH is not supported. Internal defaults use the `--forcir-internal-*` namespace; you only need to set the public `--forcir-logo-*` variables to customize. No JavaScript colour conversion—everything is handled in CSS via `@supports`.
|
|
105
|
+
|
|
106
|
+
## License
|
|
107
|
+
|
|
108
|
+
UNLICENSED
|
package/package.json
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@forcir/logo-element",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Forcir logo as vanilla JS custom elements (forcir-logo, forcir-brandmark, forcir-wordmark)",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "src/index.js",
|
|
7
|
+
"module": "src/index.js",
|
|
8
|
+
"types": "src/index.d.ts",
|
|
9
|
+
"files": ["src"],
|
|
10
|
+
"scripts": {},
|
|
11
|
+
"keywords": ["forcir", "logo", "custom-element", "web-components"],
|
|
12
|
+
"license": "UNLICENSED"
|
|
13
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/** Forcir brandmark (icon only) as a custom element. */
|
|
2
|
+
export class ForcirBrandmarkElement extends HTMLElement {
|
|
3
|
+
static get observedAttributes(): string[];
|
|
4
|
+
connectedCallback(): void;
|
|
5
|
+
attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export type ForcirBrandmarkOptions = {
|
|
9
|
+
/** SVG height in pixels. */
|
|
10
|
+
height?: number;
|
|
11
|
+
};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @typedef {Object} ForcirBrandmarkOptions
|
|
3
|
+
* @property {number} [height=18] - SVG height in pixels.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { defaultLogoStyles } from "./shared-styles.js";
|
|
7
|
+
|
|
8
|
+
const FOREGROUND_FILL = "var(--forcir-logo-foreground, var(--forcir-internal-foreground))";
|
|
9
|
+
const MUTED_FILL = "var(--forcir-logo-muted, var(--forcir-internal-muted))";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Forcir brandmark (icon only) as a custom element.
|
|
13
|
+
* @extends HTMLElement
|
|
14
|
+
*/
|
|
15
|
+
export class ForcirBrandmarkElement extends HTMLElement {
|
|
16
|
+
static get observedAttributes() {
|
|
17
|
+
return ["height"];
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
constructor() {
|
|
21
|
+
super();
|
|
22
|
+
this.attachShadow({ mode: "open" });
|
|
23
|
+
const style = document.createElement("style");
|
|
24
|
+
style.textContent = defaultLogoStyles;
|
|
25
|
+
const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
|
26
|
+
svg.setAttribute("viewBox", "0 0 154 120");
|
|
27
|
+
svg.setAttribute("aria-label", "Forcir");
|
|
28
|
+
svg.innerHTML = `
|
|
29
|
+
<path fill="${MUTED_FILL}" clip-rule="evenodd" fill-rule="evenodd" d="M49.1319 101.603L58 117.333C58 117.333 63.3333 118.667 80 118.667C93.3333 118.667 97.3333 117.333 97.3333 117.333L68.8531 66.1852L49.1319 101.603ZM41.4901 17.0436L21.4754 52.5458L2 18.0001C2 18.0001 3.95369 13.3334 14.6667 6.66673C25.3796 6.10352e-05 32 6.10352e-05 32 6.10352e-05L41.4901 17.0436Z" />
|
|
30
|
+
<path fill="${MUTED_FILL}" clip-rule="evenodd" fill-rule="evenodd" d="M106.201 17.0637L97.3333 1.33333C97.3333 1.33333 93.3333 0 80 0C63.3333 0 58 1.33333 58 1.33333L86.4802 52.4815L106.201 17.0637ZM113.843 101.623L123.333 118.667C123.333 118.667 129.954 118.667 140.667 112C151.379 105.333 153.333 100.667 153.333 100.667L133.858 66.1209L113.843 101.623Z" />
|
|
31
|
+
<path fill="${FOREGROUND_FILL}" d="M97.3333 117.333L153.333 18.0001C153.333 18.0001 151.379 13.3334 140.667 6.66676C129.954 9.15527e-05 123.333 9.15527e-05 123.333 9.15527e-05L58 117.333C58 117.333 63.3333 118.667 80 118.667C93.3333 118.667 97.3333 117.333 97.3333 117.333Z" />
|
|
32
|
+
<path fill="${FOREGROUND_FILL}" d="M97.3333 1.33333L32 118.667C32 118.667 25.3796 118.667 14.6667 112C3.95369 105.333 2 100.667 2 100.667L58 1.33333C58 1.33333 63.3333 0 80 0C93.3333 0 97.3333 1.33333 97.3333 1.33333Z" />
|
|
33
|
+
`;
|
|
34
|
+
this.shadowRoot.append(style, svg);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
connectedCallback() {
|
|
38
|
+
this._applyHeight();
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* @param {string} name
|
|
43
|
+
* @param {string|null} _oldVal
|
|
44
|
+
* @param {string|null} _newVal
|
|
45
|
+
*/
|
|
46
|
+
attributeChangedCallback(name, _oldVal, _newVal) {
|
|
47
|
+
if (name === "height") this._applyHeight();
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
_applyHeight() {
|
|
51
|
+
const h = this.getAttribute("height");
|
|
52
|
+
this.style.setProperty("--forcir-logo-height", h ? `${Number(h)}px` : "18px");
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/** Full Forcir logo (brandmark + wordmark lockup) as a custom element. */
|
|
2
|
+
export class ForcirLogoElement extends HTMLElement {
|
|
3
|
+
static get observedAttributes(): string[];
|
|
4
|
+
connectedCallback(): void;
|
|
5
|
+
attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export type ForcirLogoOptions = {
|
|
9
|
+
/** SVG height in pixels for both brandmark and wordmark. */
|
|
10
|
+
height?: number;
|
|
11
|
+
};
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @typedef {Object} ForcirLogoOptions
|
|
3
|
+
* @property {number} [height=18] - SVG height in pixels for both brandmark and wordmark.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { defaultLogoStyles } from "./shared-styles.js";
|
|
7
|
+
|
|
8
|
+
const FOREGROUND_FILL = "var(--forcir-logo-foreground, var(--forcir-internal-foreground))";
|
|
9
|
+
const MUTED_FILL = "var(--forcir-logo-muted, var(--forcir-internal-muted))";
|
|
10
|
+
|
|
11
|
+
const LOCKUP_STYLES = `
|
|
12
|
+
.lockup {
|
|
13
|
+
display: inline-flex;
|
|
14
|
+
align-items: center;
|
|
15
|
+
gap: 8px;
|
|
16
|
+
}
|
|
17
|
+
.lockup svg {
|
|
18
|
+
flex-shrink: 0;
|
|
19
|
+
}
|
|
20
|
+
`;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Full Forcir logo (brandmark + wordmark lockup) as a custom element.
|
|
24
|
+
* @extends HTMLElement
|
|
25
|
+
*/
|
|
26
|
+
export class ForcirLogoElement extends HTMLElement {
|
|
27
|
+
static get observedAttributes() {
|
|
28
|
+
return ["height"];
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
constructor() {
|
|
32
|
+
super();
|
|
33
|
+
this.attachShadow({ mode: "open" });
|
|
34
|
+
const style = document.createElement("style");
|
|
35
|
+
style.textContent = defaultLogoStyles + LOCKUP_STYLES;
|
|
36
|
+
const wrap = document.createElement("div");
|
|
37
|
+
wrap.className = "lockup";
|
|
38
|
+
|
|
39
|
+
const brandmark = document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
|
40
|
+
brandmark.setAttribute("viewBox", "0 0 154 120");
|
|
41
|
+
brandmark.setAttribute("aria-hidden", "true");
|
|
42
|
+
brandmark.innerHTML = `
|
|
43
|
+
<path fill="${MUTED_FILL}" clip-rule="evenodd" fill-rule="evenodd" d="M49.1319 101.603L58 117.333C58 117.333 63.3333 118.667 80 118.667C93.3333 118.667 97.3333 117.333 97.3333 117.333L68.8531 66.1852L49.1319 101.603ZM41.4901 17.0436L21.4754 52.5458L2 18.0001C2 18.0001 3.95369 13.3334 14.6667 6.66673C25.3796 6.10352e-05 32 6.10352e-05 32 6.10352e-05L41.4901 17.0436Z" />
|
|
44
|
+
<path fill="${MUTED_FILL}" clip-rule="evenodd" fill-rule="evenodd" d="M106.201 17.0637L97.3333 1.33333C97.3333 1.33333 93.3333 0 80 0C63.3333 0 58 1.33333 58 1.33333L86.4802 52.4815L106.201 17.0637ZM113.843 101.623L123.333 118.667C123.333 118.667 129.954 118.667 140.667 112C151.379 105.333 153.333 100.667 153.333 100.667L133.858 66.1209L113.843 101.623Z" />
|
|
45
|
+
<path fill="${FOREGROUND_FILL}" d="M97.3333 117.333L153.333 18.0001C153.333 18.0001 151.379 13.3334 140.667 6.66676C129.954 9.15527e-05 123.333 9.15527e-05 123.333 9.15527e-05L58 117.333C58 117.333 63.3333 118.667 80 118.667C93.3333 118.667 97.3333 117.333 97.3333 117.333Z" />
|
|
46
|
+
<path fill="${FOREGROUND_FILL}" d="M97.3333 1.33333L32 118.667C32 118.667 25.3796 118.667 14.6667 112C3.95369 105.333 2 100.667 2 100.667L58 1.33333C58 1.33333 63.3333 0 80 0C93.3333 0 97.3333 1.33333 97.3333 1.33333Z" />
|
|
47
|
+
`;
|
|
48
|
+
|
|
49
|
+
const wordmark = document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
|
50
|
+
wordmark.setAttribute("viewBox", "204 9 539 103");
|
|
51
|
+
wordmark.setAttribute("aria-hidden", "true");
|
|
52
|
+
wordmark.innerHTML = `
|
|
53
|
+
<path fill="${FOREGROUND_FILL}" d="M205 109.8H231.1V77.4H268V52.2H231.1V36H277V10.8H205V109.8Z" />
|
|
54
|
+
<path fill="${FOREGROUND_FILL}" d="M311.151 60.3C311.151 45.9 322.851 34.2 337.251 34.2C351.651 34.2 363.351 45.9 363.351 60.3C363.351 74.7 351.651 86.4 337.251 86.4C322.851 86.4 311.151 74.7 311.151 60.3ZM285.051 60.3C285.051 88.2 308.451 111.6 337.251 111.6C366.051 111.6 389.451 88.2 389.451 60.3C389.451 32.4 366.051 9 337.251 9C308.451 9 285.051 32.4 285.051 60.3Z" />
|
|
55
|
+
<path fill="${FOREGROUND_FILL}" d="M430.788 54V34.2H447.888C455.088 34.2 459.587 38.7 459.587 44.1C459.587 49.5 455.088 54 447.888 54H430.788ZM404.688 109.8H430.788V77.4H443.388L462.288 109.8H491.088L468.588 72C468.588 72 485.688 64.8 485.688 44.1C485.688 25.2 471.288 10.8 448.788 10.8H404.688V109.8Z" />
|
|
56
|
+
<path fill="${FOREGROUND_FILL}" d="M571.195 72C568.495 79.2 561.295 86.4 549.595 86.4C535.195 86.4 523.495 74.7 523.495 60.3C523.495 45.9 535.195 34.2 549.595 34.2C562.195 34.2 570.295 42.3 572.095 48.6L597.295 45.9C591.895 25.2 575.695 9 549.595 9C520.795 9 497.395 32.4 497.395 60.3C497.395 88.2 520.795 111.6 549.595 111.6C575.695 111.6 591.895 95.4 597.295 74.7L571.195 72Z" />
|
|
57
|
+
<path fill="${FOREGROUND_FILL}" d="M610.879 109.8H636.979V10.8H610.879V109.8Z" />
|
|
58
|
+
<path fill="${FOREGROUND_FILL}" d="M682.858 54V34.2H699.958C707.158 34.2 711.658 38.7 711.658 44.1C711.658 49.5 707.158 54 699.958 54H682.858ZM656.758 109.8H682.858V77.4H695.458L714.358 109.8H743.158L720.658 72C720.658 72 737.758 64.8 737.758 44.1C737.758 25.2 723.358 10.8 700.858 10.8H656.758V109.8Z" />
|
|
59
|
+
`;
|
|
60
|
+
|
|
61
|
+
wrap.append(brandmark, wordmark);
|
|
62
|
+
wrap.setAttribute("aria-label", "Forcir");
|
|
63
|
+
this.shadowRoot.append(style, wrap);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
connectedCallback() {
|
|
67
|
+
this._applyHeight();
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* @param {string} name
|
|
72
|
+
* @param {string|null} _oldVal
|
|
73
|
+
* @param {string|null} _newVal
|
|
74
|
+
*/
|
|
75
|
+
attributeChangedCallback(name, _oldVal, _newVal) {
|
|
76
|
+
if (name === "height") this._applyHeight();
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
_applyHeight() {
|
|
80
|
+
const h = this.getAttribute("height");
|
|
81
|
+
this.style.setProperty("--forcir-logo-height", h ? `${Number(h)}px` : "18px");
|
|
82
|
+
}
|
|
83
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/** Forcir wordmark (text only) as a custom element. */
|
|
2
|
+
export class ForcirWordmarkElement extends HTMLElement {
|
|
3
|
+
static get observedAttributes(): string[];
|
|
4
|
+
connectedCallback(): void;
|
|
5
|
+
attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export type ForcirWordmarkOptions = {
|
|
9
|
+
/** SVG height in pixels. */
|
|
10
|
+
height?: number;
|
|
11
|
+
};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @typedef {Object} ForcirWordmarkOptions
|
|
3
|
+
* @property {number} [height=18] - SVG height in pixels.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { defaultLogoStyles } from "./shared-styles.js";
|
|
7
|
+
|
|
8
|
+
const FOREGROUND_FILL = "var(--forcir-logo-foreground, var(--forcir-internal-foreground))";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Forcir wordmark (text only) as a custom element.
|
|
12
|
+
* @extends HTMLElement
|
|
13
|
+
*/
|
|
14
|
+
export class ForcirWordmarkElement extends HTMLElement {
|
|
15
|
+
static get observedAttributes() {
|
|
16
|
+
return ["height"];
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
constructor() {
|
|
20
|
+
super();
|
|
21
|
+
this.attachShadow({ mode: "open" });
|
|
22
|
+
const style = document.createElement("style");
|
|
23
|
+
style.textContent = defaultLogoStyles;
|
|
24
|
+
const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
|
25
|
+
svg.setAttribute("viewBox", "204 9 539 103");
|
|
26
|
+
svg.setAttribute("aria-label", "Forcir");
|
|
27
|
+
svg.innerHTML = `
|
|
28
|
+
<path fill="${FOREGROUND_FILL}" d="M205 109.8H231.1V77.4H268V52.2H231.1V36H277V10.8H205V109.8Z" />
|
|
29
|
+
<path fill="${FOREGROUND_FILL}" d="M311.151 60.3C311.151 45.9 322.851 34.2 337.251 34.2C351.651 34.2 363.351 45.9 363.351 60.3C363.351 74.7 351.651 86.4 337.251 86.4C322.851 86.4 311.151 74.7 311.151 60.3ZM285.051 60.3C285.051 88.2 308.451 111.6 337.251 111.6C366.051 111.6 389.451 88.2 389.451 60.3C389.451 32.4 366.051 9 337.251 9C308.451 9 285.051 32.4 285.051 60.3Z" />
|
|
30
|
+
<path fill="${FOREGROUND_FILL}" d="M430.788 54V34.2H447.888C455.088 34.2 459.587 38.7 459.587 44.1C459.587 49.5 455.088 54 447.888 54H430.788ZM404.688 109.8H430.788V77.4H443.388L462.288 109.8H491.088L468.588 72C468.588 72 485.688 64.8 485.688 44.1C485.688 25.2 471.288 10.8 448.788 10.8H404.688V109.8Z" />
|
|
31
|
+
<path fill="${FOREGROUND_FILL}" d="M571.195 72C568.495 79.2 561.295 86.4 549.595 86.4C535.195 86.4 523.495 74.7 523.495 60.3C523.495 45.9 535.195 34.2 549.595 34.2C562.195 34.2 570.295 42.3 572.095 48.6L597.295 45.9C591.895 25.2 575.695 9 549.595 9C520.795 9 497.395 32.4 497.395 60.3C497.395 88.2 520.795 111.6 549.595 111.6C575.695 111.6 591.895 95.4 597.295 74.7L571.195 72Z" />
|
|
32
|
+
<path fill="${FOREGROUND_FILL}" d="M610.879 109.8H636.979V10.8H610.879V109.8Z" />
|
|
33
|
+
<path fill="${FOREGROUND_FILL}" d="M682.858 54V34.2H699.958C707.158 34.2 711.658 38.7 711.658 44.1C711.658 49.5 707.158 54 699.958 54H682.858ZM656.758 109.8H682.858V77.4H695.458L714.358 109.8H743.158L720.658 72C720.658 72 737.758 64.8 737.758 44.1C737.758 25.2 723.358 10.8 700.858 10.8H656.758V109.8Z" />
|
|
34
|
+
`;
|
|
35
|
+
this.shadowRoot.append(style, svg);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
connectedCallback() {
|
|
39
|
+
this._applyHeight();
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* @param {string} name
|
|
44
|
+
* @param {string|null} _oldVal
|
|
45
|
+
* @param {string|null} _newVal
|
|
46
|
+
*/
|
|
47
|
+
attributeChangedCallback(name, _oldVal, _newVal) {
|
|
48
|
+
if (name === "height") this._applyHeight();
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
_applyHeight() {
|
|
52
|
+
const h = this.getAttribute("height");
|
|
53
|
+
this.style.setProperty("--forcir-logo-height", h ? `${Number(h)}px` : "18px");
|
|
54
|
+
}
|
|
55
|
+
}
|
package/src/index.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { ForcirBrandmarkElement } from "./forcir-brandmark.js";
|
|
2
|
+
export { ForcirLogoElement } from "./forcir-logo.js";
|
|
3
|
+
export { ForcirWordmarkElement } from "./forcir-wordmark.js";
|
|
4
|
+
export type { ForcirBrandmarkOptions } from "./forcir-brandmark.js";
|
|
5
|
+
export type { ForcirLogoOptions } from "./forcir-logo.js";
|
|
6
|
+
export type { ForcirWordmarkOptions } from "./forcir-wordmark.js";
|
package/src/index.js
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @forcir/logo-element
|
|
3
|
+
*
|
|
4
|
+
* Vanilla JS custom elements for the Forcir logo. Register the elements and export classes for programmatic use.
|
|
5
|
+
*
|
|
6
|
+
* Elements:
|
|
7
|
+
* - forcir-logo — full lockup (brandmark + wordmark)
|
|
8
|
+
* - forcir-brandmark — icon only
|
|
9
|
+
* - forcir-wordmark — wordmark only
|
|
10
|
+
*
|
|
11
|
+
* Pass-through CSS variables (set on the host or an ancestor):
|
|
12
|
+
* - --forcir-logo-foreground — main logo colour
|
|
13
|
+
* - --forcir-logo-muted — secondary colour (brandmark only)
|
|
14
|
+
*
|
|
15
|
+
* Attribute: height (number, default 18) — SVG height in pixels.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import { ForcirBrandmarkElement } from "./forcir-brandmark.js";
|
|
19
|
+
import { ForcirLogoElement } from "./forcir-logo.js";
|
|
20
|
+
import { ForcirWordmarkElement } from "./forcir-wordmark.js";
|
|
21
|
+
|
|
22
|
+
if (typeof customElements !== "undefined") {
|
|
23
|
+
if (!customElements.get("forcir-logo")) {
|
|
24
|
+
customElements.define("forcir-logo", ForcirLogoElement);
|
|
25
|
+
}
|
|
26
|
+
if (!customElements.get("forcir-brandmark")) {
|
|
27
|
+
customElements.define("forcir-brandmark", ForcirBrandmarkElement);
|
|
28
|
+
}
|
|
29
|
+
if (!customElements.get("forcir-wordmark")) {
|
|
30
|
+
customElements.define("forcir-wordmark", ForcirWordmarkElement);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export { ForcirBrandmarkElement, ForcirLogoElement, ForcirWordmarkElement };
|
package/src/react.d.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* React JSX typings for @forcir/logo-element.
|
|
3
|
+
* Reference this file in your tsconfig "include" (or via /// <reference />) when using
|
|
4
|
+
* the logo elements in React + TypeScript so <forcir-logo /> etc. are valid and typed.
|
|
5
|
+
* Requires @types/react in your project.
|
|
6
|
+
*/
|
|
7
|
+
/// <reference types="react" />
|
|
8
|
+
|
|
9
|
+
import type { ForcirBrandmarkElement, ForcirLogoElement, ForcirWordmarkElement } from "@forcir/logo-element";
|
|
10
|
+
|
|
11
|
+
declare global {
|
|
12
|
+
namespace JSX {
|
|
13
|
+
interface IntrinsicElements {
|
|
14
|
+
"forcir-logo": React.DetailedHTMLProps<
|
|
15
|
+
React.HTMLAttributes<ForcirLogoElement> & { height?: number },
|
|
16
|
+
ForcirLogoElement
|
|
17
|
+
>;
|
|
18
|
+
"forcir-brandmark": React.DetailedHTMLProps<
|
|
19
|
+
React.HTMLAttributes<ForcirBrandmarkElement> & { height?: number },
|
|
20
|
+
ForcirBrandmarkElement
|
|
21
|
+
>;
|
|
22
|
+
"forcir-wordmark": React.DetailedHTMLProps<
|
|
23
|
+
React.HTMLAttributes<ForcirWordmarkElement> & { height?: number },
|
|
24
|
+
ForcirWordmarkElement
|
|
25
|
+
>;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export {};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared shadow styles: OKLCH defaults with rgba fallback for browsers that don't support OKLCH.
|
|
3
|
+
* All variables use --forcir-internal-* for internal defaults and --forcir-logo-* for pass-through.
|
|
4
|
+
* @type {string}
|
|
5
|
+
*/
|
|
6
|
+
export const defaultLogoStyles = `
|
|
7
|
+
:host {
|
|
8
|
+
display: inline-block;
|
|
9
|
+
}
|
|
10
|
+
@supports (color: oklch(0 0 0)) {
|
|
11
|
+
:host {
|
|
12
|
+
--forcir-internal-foreground: oklch(0.145 0 0);
|
|
13
|
+
--forcir-internal-muted: oklch(0.556 0 0);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
@supports not (color: oklch(0 0 0)) {
|
|
17
|
+
:host {
|
|
18
|
+
--forcir-internal-foreground: rgba(0, 0, 0, 0.9);
|
|
19
|
+
--forcir-internal-muted: rgba(0, 0, 0, 0.55);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
svg {
|
|
23
|
+
display: block;
|
|
24
|
+
width: auto;
|
|
25
|
+
height: var(--forcir-logo-height, 18px);
|
|
26
|
+
}
|
|
27
|
+
`;
|