@cognitiveproof/c2pa-react-ddex-component 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/LICENSE +21 -0
- package/README.md +178 -0
- package/dist/c2pa-react-ddex-component.css +2 -0
- package/dist/c2pa-react-ddex-component.js +845 -0
- package/dist/c2pa-react-ddex-component.umd.cjs +10 -0
- package/dist/components/Ddex/DDEX_Header.d.ts +3 -0
- package/dist/components/Ddex/Ddex.d.ts +3 -0
- package/dist/components/Ddex/ddexAssertion.d.ts +93 -0
- package/dist/components/Ddex/levels/L1/DDEXL1.d.ts +7 -0
- package/dist/components/Ddex/levels/L2/DDEXL2.d.ts +7 -0
- package/dist/components/Ddex/levels/L3/DDEXL3.d.ts +7 -0
- package/dist/index.d.ts +3 -0
- package/dist/server/ddex/convert.d.ts +21 -0
- package/package.json +87 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Cognitive Proof
|
|
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.
|
package/README.md
ADDED
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
# @cognitiveproof/c2pa-react-ddex-component
|
|
2
|
+
|
|
3
|
+
A plugin for [c2pa-react-component](https://github.com/matthewrappard/c2pa-react-component) that renders [DDEX (Digital Data Exchange)](https://ddex.net/) release data — party, release, resource, and deal information carried in a C2PA manifest's `org.mixotron.ddex` custom claim — at three progressive levels of detail.
|
|
4
|
+
|
|
5
|
+
## Requirements
|
|
6
|
+
|
|
7
|
+
This package is a plugin for `c2pa-react-component`. Install both:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install @cognitiveproof/c2pa-react-ddex-component c2pa-react-component
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
### Peer dependencies
|
|
14
|
+
|
|
15
|
+
| Package | Version |
|
|
16
|
+
|---|---|
|
|
17
|
+
| `react` | `^18.0.0 \|\| ^19.0.0` |
|
|
18
|
+
| `react-dom` | `^18.0.0 \|\| ^19.0.0` |
|
|
19
|
+
|
|
20
|
+
## CSS
|
|
21
|
+
|
|
22
|
+
Import the stylesheet once at the root of your app:
|
|
23
|
+
|
|
24
|
+
```ts
|
|
25
|
+
import "@cognitiveproof/c2pa-react-ddex-component/style.css";
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
**Next.js App Router** — add it to `app/layout.tsx`:
|
|
29
|
+
|
|
30
|
+
```tsx
|
|
31
|
+
import "@cognitiveproof/c2pa-react-ddex-component/style.css";
|
|
32
|
+
|
|
33
|
+
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
|
34
|
+
return (
|
|
35
|
+
<html>
|
|
36
|
+
<body>{children}</body>
|
|
37
|
+
</html>
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Usage
|
|
43
|
+
|
|
44
|
+
Pass `DDEXManifest` as a plugin to the `C2paManifest` component from `c2pa-react-component`:
|
|
45
|
+
|
|
46
|
+
```tsx
|
|
47
|
+
import { C2paManifest } from "c2pa-react-component";
|
|
48
|
+
import { DDEXManifest } from "@cognitiveproof/c2pa-react-ddex-component";
|
|
49
|
+
import type { VerificationOutcome } from "c2pa-react-component-types";
|
|
50
|
+
import "@cognitiveproof/c2pa-react-ddex-component/style.css";
|
|
51
|
+
|
|
52
|
+
export function MediaCard({ outcome }: { outcome: VerificationOutcome }) {
|
|
53
|
+
return (
|
|
54
|
+
<C2paManifest
|
|
55
|
+
manifest={outcome}
|
|
56
|
+
plugin={[DDEXManifest]}
|
|
57
|
+
/>
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Component
|
|
63
|
+
|
|
64
|
+
### `DDEXManifest`
|
|
65
|
+
|
|
66
|
+
Renders `org.mixotron.ddex` DDEX release data from a C2PA manifest at a configurable level of detail. Returns `null` when the active manifest has no `org.mixotron.ddex` assertion.
|
|
67
|
+
|
|
68
|
+
```tsx
|
|
69
|
+
import { DDEXManifest } from "@cognitiveproof/c2pa-react-ddex-component";
|
|
70
|
+
|
|
71
|
+
<DDEXManifest manifest={verificationOutcome} level={1} />
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
#### Props
|
|
75
|
+
|
|
76
|
+
| Prop | Type | Default | Description |
|
|
77
|
+
|---|---|---|---|
|
|
78
|
+
| `manifest` | `VerificationOutcome` | required | Verification result from the C2PA SDK |
|
|
79
|
+
| `level` | `1 \| 2 \| 3` | `1` | Initial disclosure level |
|
|
80
|
+
| `className` | `string` | — | CSS class applied to the root element |
|
|
81
|
+
|
|
82
|
+
#### Disclosure levels
|
|
83
|
+
|
|
84
|
+
| Level | What is shown |
|
|
85
|
+
|---|---|
|
|
86
|
+
| `1` | Compact card: release title, artist(s), genre and parental-warning badges, "More Info" button |
|
|
87
|
+
| `2` | Extends level 1 with label, UPC, ℗/© line, track list (with ISRC), and deal summaries (commercial model, use type, price, territory, validity) |
|
|
88
|
+
| `3` | Full breakdown of the DDEX message — release, all tracks with resolved per-track artists, all deals with full territory/pricing/validity detail, the full party list, and message header (message ID and created timestamp) |
|
|
89
|
+
|
|
90
|
+
Clicking "More Info" advances from level 1 → 2 → 3. Clicking "Small View" at level 3 returns to level 1.
|
|
91
|
+
|
|
92
|
+
## Data shape
|
|
93
|
+
|
|
94
|
+
The plugin reads the `org.mixotron.ddex` assertion, which mirrors a simplified DDEX ERN message:
|
|
95
|
+
|
|
96
|
+
```ts
|
|
97
|
+
type DdexAssertion = {
|
|
98
|
+
MessageHeader?: { MessageId?: string; MessageCreatedDateTime?: string };
|
|
99
|
+
PartyList?: { PartyReference?: string; PartyName?: { FullName?: string } }[];
|
|
100
|
+
ReleaseList?: { Release?: DdexRelease[] };
|
|
101
|
+
ResourceList?: { SoundRecording?: DdexSoundRecording[] };
|
|
102
|
+
DealList?: { ReleaseDeal?: DdexReleaseDeal[] };
|
|
103
|
+
};
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
`DisplayArtist` entries reference parties by `ArtistPartyReference`, and releases reference their tracks by `ReleaseResourceReferenceList` (matched against each `SoundRecording`'s `ResourceReference`); the plugin resolves both automatically. See `examples/` for full sample manifests, including a single-track release, a multi-artist album with multiple deals, and a minimal manifest with no party or deal data.
|
|
107
|
+
|
|
108
|
+
## Converting between JSON and XML
|
|
109
|
+
|
|
110
|
+
The package also exports the JSON↔XML conversion used by the L3 "Download XML" button, so consumers can convert DDEX files to whichever format they need without depending on the `DDEXManifest` component at all:
|
|
111
|
+
|
|
112
|
+
```ts
|
|
113
|
+
import { ddexAssertionToXml, xmlToDdexAssertion } from "@cognitiveproof/c2pa-react-ddex-component";
|
|
114
|
+
import type { DdexAssertion } from "@cognitiveproof/c2pa-react-ddex-component";
|
|
115
|
+
|
|
116
|
+
// JSON -> a simplified DDEX ERN NewReleaseMessage XML document
|
|
117
|
+
const xml: string = ddexAssertionToXml(assertion);
|
|
118
|
+
|
|
119
|
+
// XML -> the same JSON assertion shape
|
|
120
|
+
const roundTripped: DdexAssertion = xmlToDdexAssertion(xml);
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
- `ddexAssertionToXml` has no environment requirements — it only builds a string.
|
|
124
|
+
- `xmlToDdexAssertion` parses with `DOMParser`, so it needs a browser or a DOM-compatible environment (e.g. jsdom in tests); it throws if `DOMParser` isn't available, and throws with a message containing `"Invalid DDEX XML"` if the input doesn't parse.
|
|
125
|
+
- Both functions omit absent sections/fields rather than emitting empty elements, so `xmlToDdexAssertion(ddexAssertionToXml(assertion))` round-trips back to a structurally equal `assertion` for any shape this project renders — see `src/server/ddex/convert.test.ts`.
|
|
126
|
+
|
|
127
|
+
## Types
|
|
128
|
+
|
|
129
|
+
Types are provided by the shared `c2pa-react-component-types` package, which is installed automatically as a dependency.
|
|
130
|
+
|
|
131
|
+
```ts
|
|
132
|
+
import type {
|
|
133
|
+
VerificationOutcome,
|
|
134
|
+
Manifest,
|
|
135
|
+
ManifestStore,
|
|
136
|
+
PluginC2PA,
|
|
137
|
+
} from "c2pa-react-component-types";
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
This package also exports its own DDEX-related types (`DdexAssertion`, `DdexRelease`, `DdexSoundRecording`, `DdexReleaseDeal`, etc.) and helper functions (`getDdexAssertion`, `getArtistNames`, `getSoundRecordingsForRelease`, `formatPrice`, and more) — see [`src/components/Ddex/ddexAssertion.ts`](src/components/Ddex/ddexAssertion.ts).
|
|
141
|
+
|
|
142
|
+
## Local development
|
|
143
|
+
|
|
144
|
+
Use [yalc](https://github.com/wclr/yalc) to consume the library in another local project without publishing to npm.
|
|
145
|
+
|
|
146
|
+
**Install yalc globally (once):**
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
npm install -g yalc
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
**Start watch mode in this repo:**
|
|
153
|
+
|
|
154
|
+
```bash
|
|
155
|
+
# Terminal 1 — rebuild on every save
|
|
156
|
+
npm run dev:lib
|
|
157
|
+
|
|
158
|
+
# Terminal 2 — push updates to yalc's local store
|
|
159
|
+
yalc push --watch
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
**In your consuming project:**
|
|
163
|
+
|
|
164
|
+
```bash
|
|
165
|
+
yalc add @cognitiveproof/c2pa-react-ddex-component
|
|
166
|
+
npm install
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
**Revert to the published npm version:**
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
yalc remove @cognitiveproof/c2pa-react-ddex-component
|
|
173
|
+
npm install
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
## License
|
|
177
|
+
|
|
178
|
+
MIT © [Cognitive Proof](https://github.com/Cognitive-Proof) — see [LICENSE](LICENSE).
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
.ddex-card{background:#fff;border-radius:12px;width:95%;padding:16px;display:inline-block;box-shadow:0 4px 20px #00000014}.ddex-header{align-items:center;gap:8px;margin-bottom:16px;display:flex}.ddex-mark{flex-shrink:0;justify-content:center;align-items:center;width:24px;height:24px;display:flex}.ddex-mark svg{width:100%;height:100%;display:block}.ddex-header-title{color:#333;font-size:14px;font-weight:600}.ddex-container{align-items:center;gap:16px;display:flex}.ddex-square{background-color:#eef2ff;border:1px solid #c7d2fe;border-radius:4px;flex-shrink:0;justify-content:center;align-items:center;width:48px;height:48px;display:flex}.ddex-logo-text{color:#3730a3;letter-spacing:-.5px;font-size:16px;font-weight:700}.ddex-summary{flex-direction:column;min-width:0;display:flex}.ddex-media-title{color:#333;overflow-wrap:anywhere;font-size:20px;font-weight:600}.ddex-artist-name{color:#666;font-size:14px}.ddex-thumbnail{object-fit:cover;border-radius:4px;width:48px;height:48px}.ddex-action{margin-top:16px}.ddex-button{color:#666;cursor:pointer;background:#fff;border:2px solid #666;border-radius:999px;width:100%;height:42px;font-size:16px;font-weight:700;transition:background-color .16s,border-color .16s,color .16s,box-shadow .16s}.ddex-button:hover{color:#fff;background:#111;border-color:#111;box-shadow:0 4px 12px #00000024}.ddex-button:focus-visible{outline-offset:3px;outline:3px solid #11111140}.ddex-button-secondary{color:#3730a3;border-color:#c7d2fe}.ddex-button-secondary:hover{color:#fff;background:#3730a3;border-color:#3730a3}.ddex-button-secondary:focus-visible{outline-color:#3730a340}.ddex-section-title{color:#333;margin-bottom:6px;font-size:16px;font-weight:600}.ddex-empty{color:#9a3412;background:#fff7ed;border:1px solid #fed7aa;border-radius:8px;margin-top:16px;padding:10px 12px;font-size:14px}.ddex-key-value{margin-top:12px}.ddex-key-value-label{color:#64748b;text-transform:uppercase;letter-spacing:.025em;margin-bottom:4px;font-size:12px;font-weight:700}.ddex-key-value-value{color:#1e293b;overflow-wrap:anywhere;font-size:15px;line-height:1.5}.ddex-divider{background:#e2e8f0;height:1px;margin:16px 0}.ddex-badges{flex-wrap:wrap;gap:6px;margin-top:12px;display:flex}.ddex-badge{color:#475569;letter-spacing:.02em;background:#f0f4f8;border:1px solid #cbd5e1;border-radius:999px;align-items:center;padding:2px 10px;font-size:12px;font-weight:600;display:inline-flex}.ddex-badge-warning{color:#991b1b;background:#fee2e2;border-color:#fecaca}.ddex-track-list{flex-direction:column;gap:8px;margin-top:10px;display:flex}.ddex-track-item{background:#f8fafc;border:1px solid #e2e8f0;border-radius:8px;padding:10px 12px}.ddex-track-title{color:#1e293b;font-size:14px;font-weight:600}.ddex-track-isrc{color:#64748b;margin-top:2px;font-size:12px}.ddex-track-meta{color:#64748b;flex-wrap:wrap;gap:10px;margin-top:2px;font-size:12px;display:flex}.ddex-deal-list{flex-direction:column;gap:10px;margin-top:10px;display:flex}.ddex-deal-item{background:#f8fafc;border:1px solid #e2e8f0;border-radius:8px;padding:10px 12px}.ddex-deal-row{flex-wrap:wrap;gap:6px;display:flex}.ddex-deal-meta{color:#475569;flex-wrap:wrap;gap:10px;margin-top:6px;font-size:13px;display:flex}.ddex-party-list{flex-direction:column;gap:6px;margin-top:10px;display:flex}.ddex-party-item{background:#f8fafc;border:1px solid #e2e8f0;border-radius:8px;justify-content:space-between;align-items:center;padding:8px 12px;font-size:13px;display:flex}.ddex-party-name{color:#1e293b;font-weight:500}.ddex-party-ref{color:#94a3b8;font-size:12px}
|
|
2
|
+
/*$vite$:1*/
|