@matterdev/credit 0.0.0-stage → 0.2.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/AGENTS.md +22 -0
- package/README.md +153 -2
- package/dist/chunk-E2CTYJ6I.js +86 -0
- package/dist/chunk-N6BHBXMD.js +118 -0
- package/dist/element.cjs +292 -0
- package/dist/element.d.cts +21 -0
- package/dist/element.d.ts +21 -0
- package/dist/element.global.js +29 -0
- package/dist/element.js +89 -0
- package/dist/index.cjs +263 -0
- package/dist/index.d.cts +102 -0
- package/dist/index.d.ts +102 -0
- package/dist/index.js +52 -0
- package/dist/native.cjs +220 -0
- package/dist/native.d.cts +26 -0
- package/dist/native.d.ts +26 -0
- package/dist/native.js +98 -0
- package/dist/react.cjs +279 -0
- package/dist/react.d.cts +112 -0
- package/dist/react.d.ts +112 -0
- package/dist/react.js +251 -0
- package/dist/url-lHz60pDq.d.cts +68 -0
- package/dist/url-lHz60pDq.d.ts +68 -0
- package/package.json +88 -4
package/AGENTS.md
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Agent guide: adding the Matter credit badge
|
|
2
|
+
|
|
3
|
+
Every product Matter Development builds shows a "Developed by Matter Development" credit, usually in the footer
|
|
4
|
+
(websites) or the About/Settings screen (apps). Use this package for it; do not hand-roll the badge or copy logo files.
|
|
5
|
+
|
|
6
|
+
1. Install: `pnpm add @matterdev/credit` (use the repo's own package manager if its lockfile says otherwise).
|
|
7
|
+
2. Pick the entry for the stack:
|
|
8
|
+
- Next.js / Vite / Electron → `import { MatterCredit } from "@matterdev/credit/react"`
|
|
9
|
+
- Expo / React Native → `import { MatterCredit } from "@matterdev/credit/native"`
|
|
10
|
+
- Astro → `import { renderCreditHTML } from "@matterdev/credit"` then `<Fragment set:html={renderCreditHTML({ source })} />`
|
|
11
|
+
- Plain HTML → `<matter-credit source="…">` with `import "@matterdev/credit/element"` or the jsDelivr script
|
|
12
|
+
3. Always pass `source` = the product's slug (e.g. `"optimo"`, `"pockly"`). It is how leads are attributed.
|
|
13
|
+
4. Matter's own products (Optimo, Pockly, …) pass `kind="product"` so the badge reads "A product of"; client work
|
|
14
|
+
keeps the default "Developed by". Ask if it is unclear whose product it is.
|
|
15
|
+
5. Leave `theme` at its default unless the design needs otherwise (`inherit` on web follows the site's text colour).
|
|
16
|
+
6. Electron: pass `onOpen={(url, e) => { e.preventDefault(); openExternal(url); }}`.
|
|
17
|
+
7. If the site has a strict CSP, allow `img-src data:` and inline styles (see README).
|
|
18
|
+
8. Look at the result in both light and dark mode before calling it done.
|
|
19
|
+
|
|
20
|
+
Placement conventions: website footer bottom row, centred (variant `stacked`); compact app footers or tight rows
|
|
21
|
+
use `inline` or `mark`; products in another language pass its `locale`: `fr`, `ar`, `es`, `pt`, `de`, `no`, `zh`,
|
|
22
|
+
`ja` or `ko`.
|
package/README.md
CHANGED
|
@@ -1,3 +1,154 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @matterdev/credit
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
The **"Developed by Matter Development"** badge for every product we ship, on every platform we build for.
|
|
4
|
+
One install, no CSS setup, follows the host's light/dark theme, and tags its link so leads on
|
|
5
|
+
matterdevelopment.com show which client site sent them.
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pnpm add @matterdev/credit
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
| Stack | Import | Usage |
|
|
12
|
+
|---|---|---|
|
|
13
|
+
| Next.js, Vite, Electron (React) | `@matterdev/credit/react` | `<MatterCredit source="optimo" />` |
|
|
14
|
+
| Expo / React Native | `@matterdev/credit/native` | `<MatterCredit source="optimo" />` |
|
|
15
|
+
| Astro (server-rendered, zero JS) | `@matterdev/credit` | `<Fragment set:html={renderCreditHTML({ source: "optimo" })} />` |
|
|
16
|
+
| Plain HTML / any framework | `@matterdev/credit/element` | `<matter-credit source="optimo"></matter-credit>` |
|
|
17
|
+
|
|
18
|
+
## Examples
|
|
19
|
+
|
|
20
|
+
### Next.js / Vite (React)
|
|
21
|
+
|
|
22
|
+
```tsx
|
|
23
|
+
import { MatterCredit } from "@matterdev/credit/react";
|
|
24
|
+
|
|
25
|
+
<footer>
|
|
26
|
+
<MatterCredit source="optimo" />
|
|
27
|
+
</footer>
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
The component carries `"use client"`, so it drops into App Router server components as is.
|
|
31
|
+
|
|
32
|
+
### Electron
|
|
33
|
+
|
|
34
|
+
Links in an Electron renderer should open in the user's browser, not a new app window:
|
|
35
|
+
|
|
36
|
+
```tsx
|
|
37
|
+
<MatterCredit
|
|
38
|
+
source="optimo-app"
|
|
39
|
+
onOpen={(url, event) => {
|
|
40
|
+
event.preventDefault();
|
|
41
|
+
window.electron.openExternal(url);
|
|
42
|
+
}}
|
|
43
|
+
/>
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Expo / React Native
|
|
47
|
+
|
|
48
|
+
```tsx
|
|
49
|
+
import { MatterCredit } from "@matterdev/credit/native";
|
|
50
|
+
|
|
51
|
+
<MatterCredit source="pockly" /> // follows the device theme
|
|
52
|
+
<MatterCredit source="pockly" color={colors.muted} /> // or your theme's text colour
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
No native modules: just `Image` + `Linking`, so it works in Expo Go and needs no rebuild.
|
|
56
|
+
To open in an in-app browser instead:
|
|
57
|
+
`onOpen={(url, e) => { e.preventDefault(); WebBrowser.openBrowserAsync(url); }}`.
|
|
58
|
+
|
|
59
|
+
### Astro
|
|
60
|
+
|
|
61
|
+
```astro
|
|
62
|
+
---
|
|
63
|
+
import { renderCreditHTML } from "@matterdev/credit";
|
|
64
|
+
---
|
|
65
|
+
<footer>
|
|
66
|
+
<Fragment set:html={renderCreditHTML({ source: "optimo" })} />
|
|
67
|
+
</footer>
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Rendered on the server: no JavaScript ships, nothing shifts when the page loads.
|
|
71
|
+
|
|
72
|
+
### Plain HTML
|
|
73
|
+
|
|
74
|
+
```html
|
|
75
|
+
<script defer src="https://cdn.jsdelivr.net/npm/@matterdev/credit@0.2.0/dist/element.global.js"
|
|
76
|
+
integrity="sha384-…" crossorigin="anonymous"></script>
|
|
77
|
+
<matter-credit source="client-site" variant="inline"></matter-credit>
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Pin the version, and copy the `integrity` hash from the file's page on jsdelivr.com, so a CDN compromise can't
|
|
81
|
+
inject script into the client's site.
|
|
82
|
+
|
|
83
|
+
With a bundler, `import "@matterdev/credit/element"` registers the same tag. Attributes:
|
|
84
|
+
`source variant theme size locale kind label nofollow no-animate href utm-medium utm-campaign utm-content`.
|
|
85
|
+
Listen for `matter-credit:open` (cancelable) to intercept the click.
|
|
86
|
+
|
|
87
|
+
## Options
|
|
88
|
+
|
|
89
|
+
| Prop | Default | |
|
|
90
|
+
|---|---|---|
|
|
91
|
+
| `source` | page hostname (web) · **required** (native) | Client/product slug → `utm_source`. Normalised: `"Optimo App"` → `optimo-app`. |
|
|
92
|
+
| `variant` | `"stacked"` | `stacked` (label above logo), `inline` (one line), `mark` (M symbol only; label becomes a tooltip). |
|
|
93
|
+
| `theme` | `"inherit"` web · `"auto"` native | See below. |
|
|
94
|
+
| `size` | `"md"` | `sm` / `md` / `lg`, or the logo height in px. |
|
|
95
|
+
| `locale` | `"en"` | `en`, `fr`, `ar` (right-to-left), `es`, `pt`, `de`, `no` (Bokmål), `zh` (Simplified), `ja`, `ko`. |
|
|
96
|
+
| `kind` | `"developed"` | `developed` ("Developed by") for client work; `product` ("A product of") for Matter's own products. |
|
|
97
|
+
| `label` | per locale and `kind` | Replaces the label text, in the visible text and the accessible name. |
|
|
98
|
+
| `nofollow` | `false` | Adds `rel="nofollow"`. By default the link passes SEO value to matterdevelopment.com. |
|
|
99
|
+
| `utm` | — | `{ medium, campaign, content, ...extra }` overrides. |
|
|
100
|
+
| `animate` | `true` | Hover sheen + arrow nudge. Always off under `prefers-reduced-motion`. |
|
|
101
|
+
| `onOpen` | — | `(url, event) => void`. Call `event.preventDefault()` to open the link yourself. |
|
|
102
|
+
| `href` | `https://matterdevelopment.com/` | Destination (http/https only). |
|
|
103
|
+
| `className`, `style` | — | Web only, merged onto the `<a>`. |
|
|
104
|
+
| `color` | — | Native only: ink colour. |
|
|
105
|
+
|
|
106
|
+
### Choosing a theme
|
|
107
|
+
|
|
108
|
+
- **`inherit`** (web default): the badge is painted in the surrounding text colour, so it follows *whatever* theme
|
|
109
|
+
system the site uses — Tailwind `.dark`, `data-theme`, a toggle, or the OS. Almost always the right choice.
|
|
110
|
+
- **`auto`**: follows the visitor's OS setting. Use it only when the site itself does; on a light-only site an
|
|
111
|
+
OS-dark visitor would get light ink on a light page.
|
|
112
|
+
- **`light` / `dark`**: name the *background* the badge sits on. `dark` = light ink.
|
|
113
|
+
|
|
114
|
+
Fine-tune with CSS custom properties on any ancestor: `--matter-credit-color`, `--matter-credit-label-color`,
|
|
115
|
+
`--matter-credit-font`, `--matter-credit-font-rtl`.
|
|
116
|
+
|
|
117
|
+
## Tracking
|
|
118
|
+
|
|
119
|
+
Every click lands on
|
|
120
|
+
|
|
121
|
+
```
|
|
122
|
+
https://matterdevelopment.com/?utm_source=<source>&utm_medium=credit_badge&utm_campaign=developed_by&utm_content=<variant>
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
(`utm_medium=app_credit` from native apps). matterdevelopment.com stores `utm_*` on contact-form leads and in PostHog.
|
|
126
|
+
The link uses `rel="noopener"` without `noreferrer`, so the referring page is reported too.
|
|
127
|
+
|
|
128
|
+
## SEO: who built this site
|
|
129
|
+
|
|
130
|
+
```tsx
|
|
131
|
+
import { MatterCreditJsonLd } from "@matterdev/credit/react";
|
|
132
|
+
<MatterCreditJsonLd name="Optimo" url="https://optimo.app" />
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Or `creatorJsonLdScript({ name, url })` for an HTML string. If the site already has a JSON-LD `WebSite` node,
|
|
136
|
+
add `creator: MATTER_ORGANIZATION` to it instead of emitting a second one.
|
|
137
|
+
|
|
138
|
+
## Content Security Policy
|
|
139
|
+
|
|
140
|
+
The logo is inlined as a `data:` image used as a CSS mask, and the web renderers include a `<style>` element.
|
|
141
|
+
A strict CSP needs `img-src data:` and `style-src 'unsafe-inline'` (or a nonce). The custom element uses shadow DOM
|
|
142
|
+
styles, which follow the same rule.
|
|
143
|
+
|
|
144
|
+
## Developing
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
pnpm install
|
|
148
|
+
pnpm test # vitest: core, React, custom element, React Native (via react-native-web)
|
|
149
|
+
pnpm typecheck
|
|
150
|
+
pnpm demo # builds, renders every variant to demo/index.html, screenshots light + dark
|
|
151
|
+
pnpm assets # regenerate inlined logos after replacing a file in assets/ (needs Python + Pillow)
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
Releasing: bump `version`, then `pnpm publish` (runs typecheck, tests and build first).
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import {
|
|
2
|
+
resolveCredit
|
|
3
|
+
} from "./chunk-N6BHBXMD.js";
|
|
4
|
+
|
|
5
|
+
// src/core/assets.generated.ts
|
|
6
|
+
var WORDMARK_MASK = "data:image/webp;base64,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";
|
|
7
|
+
var MARK_MASK = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0ODIuNzIgMzUxLjY4Ij48cGF0aCBkPSJNNzYuNTQsMzQ5LjY3YzIuMzktLjcyLDQuMTUtMS40NSw1Ljg1LTIuMTcsNS4xNC0yLjE2LDEzLjAxLTUuNTQsMjAuMjgtMTIuODMsNC45My00Ljk0LDcuODQtOS45Miw5LjQ3LTEyLjc1LDAsMCwxLjcyLTIuOTksMy4yMS02LjMxLDE0LjAyLTMxLjMyLDExLjQtNzQuNjksMTEuNC03NC42OS0xLjc1LTI0LjUyLTYuNTktNDYuNTQtMTUuOTgtNzIuNTYtNC45My0xMy42Ni00LjctMTMuMTYtMTkuOTYtNDUuMjItNC44OS0xMC4zMS04LjI3LTE3LjYtMTAuNDEtMjIuNjItMS42Ni0zLjg5LTUuNC0xNC4zOS03LjU0LTIxLjE4LS41LTEuNTgtLjk5LTMuMzQtMS40Ni01LjY1LS45Ny00Ljc5LTEuMDMtOC4yNy0xLjA5LTE0LjA0LS4xLTkuMjksLjc0LTEyLjQ1LDEuMjktMTQuMjIsLjE5LS42MSwuNTktMS44NiwxLjI3LTMuMzMsNi4yMS0xMy40OSwxNC44LTE4LjA5LDI5LjIyLTE1LjYsNy44NSwxLjM1LDEyLDMuMTEsMjAuNzMsOC43OCwxMy40Nyw4Ljc3LDMwLjQ5LDI4LjQ1LDQ0Ljk0LDUyLjA1LDIuNzksNC41Niw0Ljc5LDguMDYsNi4xMiwxMC41NywyLjgsNS4yOSw0LjQ2LDkuMTQsNy42MywxNi41NSw0LjU2LDEwLjY1LDYuODQsMTUuOTcsOC4xNiwyMC40NSwuOTIsMy4xMSwyLjI3LDYuOTUsNC45OCwxNC42MiwuMTEsLjMyLC41MywxLjMxLDEuMzgsMy4yOCwxLjA3LDIuNSwxLjMxLDIuOTcsMS44LDMuMTgsMS4yLC41MSwyLjg0LS45Myw0LjM0LTIuMjMsMy4wNi0yLjYzLDYuMzEtNS4wNSw5LjMyLTcuNzMsNS41OC00Ljk3LDYuNDEtNS41Miw2Ljc4LTcuMjEsLjQyLTEuODktLjE4LTMuMTctMS45OC04LjAxLTIuODctNy43Mi0yLjM1LTYuMi0zLjU1LTEwLjAzLTQuNjMtMTQuODctMjIuNDMtNDguOC0zNS4yOS02Ny4zLTYuNS05LjM2LTEzLjgtMTcuODYtMjEuNTEtMjUuMDJDMTM2LjQxLDEwLjI1LDEyNC4wNSwzLjU0LDEwNC44OSwuNzJjLTExLjY3LTEuNzMtMjIuNTMtLjM2LTMzLjM5LDQuMi0xMC4yLDQuMjctMTYuMDgsOS44OS0yMS4yNywyMC4zNC04LjU0LDE3LjI2LTguOCwzNy4xMS0uOCw2MS43OSw0Ljk1LDE1LjMsNi43MSwxOS41OSwxNC4xNiwzNC42NywxMS42MiwyMy41OSwxNS4xMywzMS44MiwyMS4zNyw1MC40MSwyLjYxLDcuNzgsNS4xOSwxNi4yNiw1Ljc0LDE4Ljg1czIuMDYsOS4zNywzLjM1LDE1LjA4YzQuNjksMjAuNjUsNi4zOCwzNS4zNSw2LjI5LDU0LjY1LS4xMiwyNC41Ny0yLjUxLDM2LjU5LTkuNzUsNDkuMTMtMi4xOSwzLjc5LTQuNTEsNi40OS01LjEsNy4xMi00LjU5LDQuOTMtOS4yMiw2LjkzLTEwLjE0LDcuMzItLjU5LC4yNS0yLjU1LDEuMDUtNS4yNSwxLjYxLS43NywuMTYtMy41NywuNjMtNy42NiwuNi04LjczLS4wNS0xMy4wOS0xLjkyLTIwLjAxLTguNjEtOS41NS05LjIzLTEzLjI1LTIxLjUxLTE1Ljc5LTUyLjQ1LTIuMTEtMjUuNTksMy4zNS01OS4zOCwxMy41Ny04My45MSw2LjM1LTE1LjIyLDEyLjM1LTI4LjI5LDE0LjAxLTMwLjQ3LC45Ny0xLjI3LDEuNS0yLjMxLDEuNTctMy40LC4wNy0xLjE3LS4yNi0yLjE5LTMuMDItNi4yMy0yLjU0LTMuNzItMi4xNC0yLjctNS4yNC02Ljk2LTEuNjEtMi4yMS0xLjkyLTIuNzYtMi42OC0yLjg4LTEuODMtLjI4LTMuNjMsMi4zNS01Ljk2LDUuODQtNC45MSw3LjM2LTcuMzcsMTEuMDQtNy4zOCwxMS4wNy0xMC4wMywxNC45MS0xOSwzMi45OC0yMi45OCw0Ni4yNkMxLjY5LDIxNy42MSwuMTgsMjI4LjQ3LDAsMjU1LjQ2Yy0uMTcsMjkuMTksMi40Niw0NC4wMywxMS4xLDYyLjc0LDQuMDYsOC43Nyw4LjgyLDE1LjQ0LDE0Ljg3LDIwLjU1LDcuMTMsNi4wMiwxNC4xMiw4LjQ4LDE3LjcxLDkuNyw0LjAyLDEuMzYsMTcuNjQsNS43OCwzMi44NSwxLjIyWiIvPjxwYXRoIGQ9Ik0yNTcuMjQsMzI2LjU0YzcuMDItMi40NCwxNy40My04LjY1LDIxLjUxLTEyLjg1LDkuNTEtOS43NSwxNi45NS0yNS41MiwxOS44NS00Mi4wNCwyLjQ3LTE0LjIsMS41NC0zNi42My0yLjMtNTQuMjgtNC4yOS0xOS43NC0xMS42Ni0zOS42LTE3LjI5LTM5LjEtLjg1LC4wOC0xLjE2LC41Ny01LjY5LDQuMDEtMy42MiwyLjc0LTYuNjEsNC44NC04LjUsNi4xNC0xLjA2LDEuMDItMi4xMiwyLjA1LTMuMTgsMy4wNywxLjQ3LDQuMDcsMi45NCw4LjE0LDQuNDEsMTIuMjEsMy41NiwxMC43Miw0LjkxLDE1Ljc0LDcuNjYsMjguMjYsLjUyLDIuMzMsLjk5LDEwLjE5LDEuMDQsMTcuNDMsLjA5LDEwLjk2LS4yOCwxNC42My0yLjA4LDIxLjY3LTUuMTUsMTkuOTctMTEuOTEsMjguNTktMjYuMjIsMzMuMzktMTUuNjUsNS4yNy0yOS45NS0uNTUtMzcuMDktMTUuMDgtNi43NC0xMy44LTUuNC00NC43OSwyLjg0LTY0LjQyLDEwLjY0LTI1LjMyLDI3LjQ0LTQ4LjAxLDQ0LjQzLTU5Ljk1LDIuODUtMi4wMSw3LjUyLTUuMzMsMTAuMzgtNy40LDIwLjQ2LTE0Ljg1LDQ4LjQ0LTI0LjE2LDc2LjA3LTI1LjI4LDcuNDItLjI5LDEyLjgxLS45MiwxMy4zMi0xLjU0LC40NS0uNTcsMS4wNC01LjAxLDEuMy05Ljg3LC42Ni0xMS45MywuMjEtMTIuMzYtMTIuMjQtMTIuMzYtOS42MywwLTIyLjksMS4yNi0zMC44NywyLjk0LTguMDIsMS42OC0xMi44MywzLjI1LTMwLjE0LDkuODYtNy41NiwyLjg3LTI0LjI0LDExLjA3LTMzLjkzLDE2LjY3LTIwLjUxLDExLjg1LTM5Ljc5LDMwLjk5LTUzLjg4LDUzLjUyLTQuMDUsNi40My0xMi41NCwyMy43My0xMi41NCwyNS40OSwwLC41NS0uNjIsMi4zMy0xLjM4LDMuOTgtMi41Niw1LjUyLTQuNDMsMTMuNTQtNS40LDIzLjIyLS4yOSwyLjk0LS4zNSw1Ljk2LS40NywxMS45OS0uMDcsMy40NC0uMTMsNi45NSwwLDExLjU3LC4yMiw3LjQ1LC40LDEyLjcyLDIuMDUsMTkuNSwuNTksMi40NCwxLjE2LDQuMjEsMS41OCw1LjQ4LDIuNDEsNy40Miw0LjY0LDE0LjMsMTAuMzYsMjAuNjMsMy45OSw0LjQyLDguMTcsNi45LDEwLjE3LDguMDcsMy43LDIuMTYsNi45OCwzLjM3LDEwLjkxLDQuODEsMy40OSwxLjI5LDYuMjUsMS45Nyw2Ljk2LDIuMTQsLjQzLC4xLC43OSwuMTksMS4wNiwuMjUsNy44OCwxLjc2LDE0LjEzLDEuNTEsMTguMywxLjMyLDYuODktLjMyLDExLjg1LTEuNDYsMTMuMzgtMS44MywwLDAsMi45My0uNjgsNS42My0xLjYyWiIvPjxwYXRoIGQ9Ik00NDEuMzIsMzQ0Ljg3YzEzLjM4LTUuODgsMTguODMtMTAuMjIsMjYuMTUtMjAuOCw1LjU5LTguMDgsOC44Mi0xNC45OSwxMS40NS0yNC41LDQuODEtMTcuNDMsNS4xMi02MC41OSwuNTktODEuMjktNC4wNS0xOC40Ny0xMS45OC0zOS4zMi0yMC40MS01My42Ni0uOTItMS41Ni0zLjM5LTUuODEtNS41Mi05LjQyLTcuNTctMTIuODYtOS4xNC0xNy41OS0xMS44Ni0xNy40My0xLjU1LC4wOS0xLjYxLDEuNjMtNi44MSw4LjQtNC4xMiw1LjM2LTUuMTgsNS44Mi01LjgsOC4wNi0uNjgsMi40OC0uNzMsNS4wMywzLjA4LDExLjcxLDUuNzksMTAuMTcsOS43NSwxOC4wNSwxMS45NywyMy44MywxLjA1LDIuNzUsMi4yOCw1Ljg1LDIuNzEsNi44OCw0LjE1LDkuNzksOC40NywzMS40NCw5LjY1LDQ4LjMzLDIuODIsNDAuMzYtNS42LDY4LjA2LTIyLjk1LDc1LjU5LTYuODEsMi45Ni0xNy4yMiwzLjYtMjIuOTEsMS40NC0zLjU2LTEuMzUtNS45OC0yLjg2LTguMTgtNC4zOS0yLjItMS41My0xMy41NS05LjcyLTE3LjE4LTI0LjgxLS4zNy0xLjUyLS41Ni0yLjk3LS45Ni01Ljg3LTEuMTUtOC40MS0uODYtMTQuNzYtLjg2LTIyLjkxLDAtMjIuMzksLjQ1LTI2LjI5LDUuNjktNDguNTIsMi45NC0xMi40OSw5LjQ2LTMzLjE5LDEzLjUyLTQyLjg3LDEuNjMtMy44OSwzLjMtOC4xMywzLjc1LTkuNDIsLjQzLTEuMywxLjYzLTQuMDUsMi42Ni02LjEyLDcuMzctMTQuOCwxOC40LTQ0LjQxLDE5LjU4LTUyLjU0LC4zMS0yLjIsMS4yNS02LjU1LDIuMDYtOS42NSwyLjIzLTguNTgsMi4wOS00Mi4yMS0uMjEtNDkuOTQtNC44Mi0xNi4yNy0xMi41OS0yNy4xLTI0LjA3LTMzLjYyLTcuODktNC40OC0xMy43Ny01Ljg0LTI1LjQ2LTUuOS0yNC4zMS0uMTQtNDQuMTgsOS4yNS02NC4xNiwzMC4zLTE3LjA3LDE3Ljk4LTI2LjQ0LDMxLjMtMzYuNDIsNTEuNzQtNi45OSwxNC4zLTEwLDIyLjUtOS40OSwyNS45NywuMjQsMS43MywuODYsMi4xNCwzLjEzLDIuMDksNC43Mi0uMTIsMTcuNzMtMy4yMywyMC42OC00Ljk2LDIuNzctMS41OSw5Ljg3LTExLjMzLDE1LjYzLTIxLjM5LDYuMzUtMTEuMSwxNC44Ny0yMi43NywyNC4yNC0zMy4xNyw3LjA0LTcuODIsMjEuMjktMTkuMiwyNy42Ny0yMi4xLDUuMzYtMi40NCwxNC40NC0zLjg3LDIxLjA2LTMuMzQsMi45LC4yMyw1LjM4LC44Nyw3LjYxLDIuMDMsMS45OCwxLjAzLDUuMzksMy4yMSw4LjY5LDguNzksNi40OSwxMC45NSw2LjU0LDI0LjY0LDYuNDksMjguNDYtLjE3LDEzLjE2LTIuOTcsMjIuOTUtNS4zOCwzMS4xNC0zLjUsMTEuOTEtOC40LDIzLjAzLTE4LjMsNDUuMjItMy44Niw4LjY1LTYuNCwxNC45NC0xMS4zNiwyOC4yNy0uNjcsMS44Mi0yLjE2LDYuNDctMy4yOSwxMC4zNi0xLjEyLDMuODctMi42MSw4Ljk4LTMuMzIsMTEuMzEtLjY3LDIuMzItMS45Miw3LjQyLTIuNzMsMTEuMzEtLjgsMy44Ny0xLjg1LDguNTQtMi4zNSwxMC4zNi0uNSwxLjgyLTEuODMsMTAuOTMtMi45NiwyMC4yNS0zLjEsMjUuNjYtMS43OCw0NS4zNiw0LjMyLDY0LjA5LDEuNjIsNC45OCwzLjY1LDkuNDEsMy42NSw5LjQxLC4zNiwuNzMsMS4wOSwyLjEzLDIuMjEsMy45OSwyLjU1LDQuMjEsNy4yMSwxMS45MSwxNS43OSwxOS4xMSwyLjA3LDEuNzQsNS4yMSw0LjMsOS44Nyw2Ljc4LDIuNTIsMS4zNCw1LjE0LDIuNCw4LjQ5LDMuNTUsMy41NywxLjIyLDYuMzUsMS44MSw2Ljg5LDEuOTMsNS41MywxLjE4LDkuNjUsMS4wOSwxNi4yOCwuOTYsOC4xNS0uMTcsMTEuNTQtMS4wMiwxMy42My0xLjY2LDEuNTItLjQ3LDIuNjItLjg4LDMuNzItMS4zNloiLz48L3N2Zz4=";
|
|
8
|
+
|
|
9
|
+
// src/core/css.ts
|
|
10
|
+
var LIGHT_INK = "#1F2A3B";
|
|
11
|
+
var DARK_INK = "#F3F5F7";
|
|
12
|
+
var CREDIT_CSS = `
|
|
13
|
+
.mdc.mdc{color:var(--matter-credit-color);text-decoration:none;font-family:var(--matter-credit-font,ui-monospace,SFMono-Regular,Menlo,Consolas,"Liberation Mono",monospace)}
|
|
14
|
+
.mdc.mdc--light{color:var(--matter-credit-color,${LIGHT_INK})}
|
|
15
|
+
.mdc.mdc--dark{color:var(--matter-credit-color,${DARK_INK})}
|
|
16
|
+
.mdc.mdc--auto{color:var(--matter-credit-color,${LIGHT_INK})}
|
|
17
|
+
@media (prefers-color-scheme:dark){.mdc.mdc--auto{color:var(--matter-credit-color,${DARK_INK})}}
|
|
18
|
+
.mdc{display:inline-flex;align-items:center;gap:.6em;vertical-align:middle;line-height:1;border-radius:6px;-webkit-tap-highlight-color:transparent}
|
|
19
|
+
.mdc--stacked{flex-direction:column}
|
|
20
|
+
.mdc--mark{gap:.35em}
|
|
21
|
+
.mdc:focus-visible{outline:2px solid currentColor;outline-offset:4px}
|
|
22
|
+
.mdc__label{font-size:var(--mdc-label-size,11px);font-weight:400;letter-spacing:.14em;text-transform:uppercase;white-space:nowrap;opacity:.7;color:var(--matter-credit-label-color)}
|
|
23
|
+
.mdc--stacked .mdc__label{margin-inline-end:-.14em}
|
|
24
|
+
.mdc[dir=rtl] .mdc__label{letter-spacing:0;margin-inline-end:0;text-transform:none;font-family:var(--matter-credit-font-rtl,system-ui,sans-serif)}
|
|
25
|
+
.mdc__row{display:inline-flex;align-items:center;gap:6px}
|
|
26
|
+
.mdc__logo--wordmark{--mdc-logo:url("${WORDMARK_MASK}")}
|
|
27
|
+
.mdc__logo--mark{--mdc-logo:url("${MARK_MASK}")}
|
|
28
|
+
.mdc__logo{display:block;flex:none;background-color:currentColor;opacity:.85;transition:opacity .2s ease;-webkit-print-color-adjust:exact;print-color-adjust:exact;-webkit-mask-image:var(--mdc-logo);mask-image:var(--mdc-logo);-webkit-mask-size:100% 100%;mask-size:100% 100%;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat}
|
|
29
|
+
.mdc:hover .mdc__logo,.mdc:focus-visible .mdc__logo{opacity:1}
|
|
30
|
+
.mdc__ext{display:block;flex:none;opacity:.6;transition:transform .25s ease,opacity .2s ease}
|
|
31
|
+
.mdc:hover .mdc__ext{opacity:.9}
|
|
32
|
+
.mdc[dir=rtl] .mdc__ext{transform:scaleX(-1)}
|
|
33
|
+
@media (prefers-reduced-motion:no-preference){
|
|
34
|
+
.mdc--animate .mdc__logo{-webkit-mask-image:var(--mdc-logo),linear-gradient(105deg,#000 40%,rgba(0,0,0,.3) 50%,#000 60%);mask-image:var(--mdc-logo),linear-gradient(105deg,#000 40%,rgba(0,0,0,.3) 50%,#000 60%);-webkit-mask-size:100% 100%,300% 100%;mask-size:100% 100%,300% 100%;-webkit-mask-position:0 0,100% 0;mask-position:0 0,100% 0;-webkit-mask-composite:source-in;mask-composite:intersect}
|
|
35
|
+
.mdc--animate:hover .mdc__logo{-webkit-mask-position:0 0,0 0;mask-position:0 0,0 0;transition:opacity .2s ease,-webkit-mask-position .9s ease,mask-position .9s ease}
|
|
36
|
+
.mdc--animate:hover .mdc__ext{transform:translate(2px,-2px)}
|
|
37
|
+
.mdc--animate[dir=rtl]:hover .mdc__ext{transform:scaleX(-1) translate(2px,-2px)}
|
|
38
|
+
}
|
|
39
|
+
@media (forced-colors:active){.mdc__logo{forced-color-adjust:none;background-color:LinkText}}
|
|
40
|
+
`.trim();
|
|
41
|
+
var EXTERNAL_ICON_PATHS = [
|
|
42
|
+
"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6",
|
|
43
|
+
"M15 3h6v6M10 14 21 3"
|
|
44
|
+
];
|
|
45
|
+
|
|
46
|
+
// src/core/html.ts
|
|
47
|
+
var ESCAPES = {
|
|
48
|
+
"&": "&",
|
|
49
|
+
"<": "<",
|
|
50
|
+
">": ">",
|
|
51
|
+
'"': """,
|
|
52
|
+
"'": "'"
|
|
53
|
+
};
|
|
54
|
+
function escapeHtml(value) {
|
|
55
|
+
return value.replace(/[&<>"']/g, (c) => ESCAPES[c]);
|
|
56
|
+
}
|
|
57
|
+
function externalIconSvg(size) {
|
|
58
|
+
const paths = EXTERNAL_ICON_PATHS.map((d) => `<path d="${d}"/>`).join("");
|
|
59
|
+
return `<svg class="mdc__ext" width="${size}" height="${size}" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false">${paths}</svg>`;
|
|
60
|
+
}
|
|
61
|
+
function renderCreditMarkup(model) {
|
|
62
|
+
const attrs = [
|
|
63
|
+
`class="${model.className}"`,
|
|
64
|
+
`href="${escapeHtml(model.href)}"`,
|
|
65
|
+
`target="_blank"`,
|
|
66
|
+
`rel="${model.rel}"`,
|
|
67
|
+
`dir="${model.dir}"`,
|
|
68
|
+
`lang="${model.lang}"`,
|
|
69
|
+
`aria-label="${escapeHtml(model.ariaLabel)}"`,
|
|
70
|
+
model.title ? `title="${escapeHtml(model.title)}"` : null,
|
|
71
|
+
`style="--mdc-label-size:${model.labelSize}px"`,
|
|
72
|
+
`data-matter-credit=""`
|
|
73
|
+
].filter(Boolean).join(" ");
|
|
74
|
+
const label = model.label ? `<span class="mdc__label" aria-hidden="true">${escapeHtml(model.label)}</span>` : "";
|
|
75
|
+
const logo = `<span class="mdc__logo mdc__logo--${model.logo.kind}" aria-hidden="true" style="width:${model.logo.width}px;height:${model.logo.height}px"></span>`;
|
|
76
|
+
return `<a ${attrs}>${label}<span class="mdc__row">${logo}${externalIconSvg(model.iconSize)}</span></a>`;
|
|
77
|
+
}
|
|
78
|
+
function renderCreditHTML(options) {
|
|
79
|
+
return `<style data-matter-credit>${CREDIT_CSS}</style>${renderCreditMarkup(resolveCredit(options))}`;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export {
|
|
83
|
+
CREDIT_CSS,
|
|
84
|
+
renderCreditMarkup,
|
|
85
|
+
renderCreditHTML
|
|
86
|
+
};
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
// src/core/labels.ts
|
|
2
|
+
var BRAND_NAME = "Matter Development";
|
|
3
|
+
var LOCALES = {
|
|
4
|
+
en: { label: "Developed by", productLabel: "A product of", newTab: "opens in a new tab", opensBrowser: "opens in your browser", dir: "ltr" },
|
|
5
|
+
fr: { label: "D\xE9velopp\xE9 par", productLabel: "Un produit de", newTab: "s\u2019ouvre dans un nouvel onglet", opensBrowser: "s\u2019ouvre dans votre navigateur", dir: "ltr" },
|
|
6
|
+
ar: { label: "\u062A\u0645 \u0627\u0644\u062A\u0637\u0648\u064A\u0631 \u0628\u0648\u0627\u0633\u0637\u0629", productLabel: "\u0623\u062D\u062F \u0645\u0646\u062A\u062C\u0627\u062A", newTab: "\u064A\u0641\u062A\u062D \u0641\u064A \u0639\u0644\u0627\u0645\u0629 \u062A\u0628\u0648\u064A\u0628 \u062C\u062F\u064A\u062F\u0629", opensBrowser: "\u064A\u0641\u062A\u062D \u0641\u064A \u0627\u0644\u0645\u062A\u0635\u0641\u062D", dir: "rtl" },
|
|
7
|
+
es: { label: "Desarrollado por", productLabel: "Un producto de", newTab: "se abre en una pesta\xF1a nueva", opensBrowser: "se abre en tu navegador", dir: "ltr" },
|
|
8
|
+
pt: { label: "Desenvolvido por", productLabel: "Um produto de", newTab: "abre em uma nova aba", opensBrowser: "abre no seu navegador", dir: "ltr" },
|
|
9
|
+
de: { label: "Entwickelt von", productLabel: "Ein Produkt von", newTab: "\xF6ffnet in einem neuen Tab", opensBrowser: "\xF6ffnet im Browser", dir: "ltr" },
|
|
10
|
+
no: { label: "Utviklet av", productLabel: "Et produkt fra", newTab: "\xE5pnes i en ny fane", opensBrowser: "\xE5pnes i nettleseren", dir: "ltr" },
|
|
11
|
+
zh: { label: "\u5F00\u53D1\u8005", productLabel: "\u51FA\u54C1", newTab: "\u5728\u65B0\u6807\u7B7E\u9875\u4E2D\u6253\u5F00", opensBrowser: "\u5728\u6D4F\u89C8\u5668\u4E2D\u6253\u5F00", dir: "ltr" },
|
|
12
|
+
ja: { label: "\u958B\u767A", productLabel: "\u63D0\u4F9B", newTab: "\u65B0\u3057\u3044\u30BF\u30D6\u3067\u958B\u304D\u307E\u3059", opensBrowser: "\u30D6\u30E9\u30A6\u30B6\u3067\u958B\u304D\u307E\u3059", dir: "ltr" },
|
|
13
|
+
ko: { label: "\uAC1C\uBC1C", productLabel: "\uC81C\uACF5", newTab: "\uC0C8 \uD0ED\uC5D0\uC11C \uC5F4\uB9BC", opensBrowser: "\uBE0C\uB77C\uC6B0\uC800\uC5D0\uC11C \uC5F4\uB9BC", dir: "ltr" }
|
|
14
|
+
};
|
|
15
|
+
var LOCALE_CODES = Object.keys(LOCALES);
|
|
16
|
+
function localeStrings(locale) {
|
|
17
|
+
return LOCALES[locale ?? "en"] ?? LOCALES.en;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// src/core/url.ts
|
|
21
|
+
var MATTER_URL = "https://matterdevelopment.com/";
|
|
22
|
+
function normalizeSource(source) {
|
|
23
|
+
return source.trim().toLowerCase().replace(/^www\./, "").replace(/[^a-z0-9._-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 100);
|
|
24
|
+
}
|
|
25
|
+
function safeUrl(href) {
|
|
26
|
+
try {
|
|
27
|
+
const url = new URL(href);
|
|
28
|
+
if (url.protocol === "https:" || url.protocol === "http:") return url;
|
|
29
|
+
} catch {
|
|
30
|
+
}
|
|
31
|
+
return new URL(MATTER_URL);
|
|
32
|
+
}
|
|
33
|
+
function buildCreditUrl(options = {}) {
|
|
34
|
+
const { source, utm = {}, variant, defaultMedium = "credit_badge", href = MATTER_URL } = options;
|
|
35
|
+
const { medium, campaign, content, ...extra } = utm;
|
|
36
|
+
const url = safeUrl(href);
|
|
37
|
+
const set = (key, value) => {
|
|
38
|
+
if (value) url.searchParams.set(key, value);
|
|
39
|
+
};
|
|
40
|
+
set("utm_source", source ? normalizeSource(source) : void 0);
|
|
41
|
+
set("utm_medium", medium ?? defaultMedium);
|
|
42
|
+
set("utm_campaign", campaign ?? "developed_by");
|
|
43
|
+
set("utm_content", content ?? variant);
|
|
44
|
+
for (const [key, value] of Object.entries(extra)) set(key, value);
|
|
45
|
+
return url.toString();
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// src/core/metrics.generated.ts
|
|
49
|
+
var WORDMARK_RATIO = 4.2755;
|
|
50
|
+
var MARK_RATIO = 1.3726;
|
|
51
|
+
|
|
52
|
+
// src/core/model.ts
|
|
53
|
+
var LOGO_HEIGHT = {
|
|
54
|
+
stacked: { sm: 20, md: 28, lg: 36 },
|
|
55
|
+
inline: { sm: 16, md: 20, lg: 26 },
|
|
56
|
+
mark: { sm: 18, md: 24, lg: 32 }
|
|
57
|
+
};
|
|
58
|
+
var LABEL_SIZE = {
|
|
59
|
+
stacked: { sm: 10, md: 11, lg: 13 },
|
|
60
|
+
inline: { sm: 11, md: 12, lg: 14 },
|
|
61
|
+
mark: { sm: 11, md: 12, lg: 14 }
|
|
62
|
+
};
|
|
63
|
+
var round = (n) => Math.round(n * 100) / 100;
|
|
64
|
+
function sizes(variant, size) {
|
|
65
|
+
if (typeof size === "number" && size > 0) {
|
|
66
|
+
return { height: size, label: Math.min(16, Math.max(10, Math.round(size * 0.42))) };
|
|
67
|
+
}
|
|
68
|
+
const key = size === "sm" || size === "lg" ? size : "md";
|
|
69
|
+
return { height: LOGO_HEIGHT[variant][key], label: LABEL_SIZE[variant][key] };
|
|
70
|
+
}
|
|
71
|
+
function resolveCredit(options = {}, platform = "web") {
|
|
72
|
+
const variant = options.variant ?? "stacked";
|
|
73
|
+
const theme = options.theme ?? "inherit";
|
|
74
|
+
const strings = localeStrings(options.locale);
|
|
75
|
+
const label = options.label?.trim() || (options.kind === "product" ? strings.productLabel : strings.label);
|
|
76
|
+
const { height, label: labelSize } = sizes(variant, options.size);
|
|
77
|
+
const ratio = variant === "mark" ? MARK_RATIO : WORDMARK_RATIO;
|
|
78
|
+
return {
|
|
79
|
+
variant,
|
|
80
|
+
theme,
|
|
81
|
+
href: buildCreditUrl({
|
|
82
|
+
source: options.source,
|
|
83
|
+
utm: options.utm,
|
|
84
|
+
variant,
|
|
85
|
+
defaultMedium: platform === "native" ? "app_credit" : "credit_badge",
|
|
86
|
+
href: options.href
|
|
87
|
+
}),
|
|
88
|
+
rel: options.nofollow ? "noopener nofollow" : "noopener",
|
|
89
|
+
dir: strings.dir,
|
|
90
|
+
lang: options.locale && options.locale in LOCALES ? options.locale : "en",
|
|
91
|
+
label: variant === "mark" ? null : label,
|
|
92
|
+
ariaLabel: `${label} ${BRAND_NAME} (${platform === "native" ? strings.opensBrowser : strings.newTab})`,
|
|
93
|
+
title: variant === "mark" ? `${label} ${BRAND_NAME}` : void 0,
|
|
94
|
+
className: [
|
|
95
|
+
"mdc",
|
|
96
|
+
`mdc--${variant}`,
|
|
97
|
+
`mdc--${theme}`,
|
|
98
|
+
options.animate === false ? null : "mdc--animate"
|
|
99
|
+
].filter(Boolean).join(" "),
|
|
100
|
+
logo: {
|
|
101
|
+
kind: variant === "mark" ? "mark" : "wordmark",
|
|
102
|
+
width: round(height * ratio),
|
|
103
|
+
height
|
|
104
|
+
},
|
|
105
|
+
labelSize,
|
|
106
|
+
iconSize: Math.max(10, Math.round(variant === "stacked" ? height * 0.46 : labelSize))
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export {
|
|
111
|
+
BRAND_NAME,
|
|
112
|
+
LOCALES,
|
|
113
|
+
LOCALE_CODES,
|
|
114
|
+
MATTER_URL,
|
|
115
|
+
normalizeSource,
|
|
116
|
+
buildCreditUrl,
|
|
117
|
+
resolveCredit
|
|
118
|
+
};
|