@colixsystems/widget-sdk 0.149.0 → 0.150.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 CHANGED
@@ -72,7 +72,32 @@ See the design reference for the full architecture: [`docs/architecture/widget-m
72
72
 
73
73
  ## Status
74
74
 
75
- `v0.148.0` — pre-publish. The package surface (types, function names, export paths) is the v1 contract; runtime behaviour for some hooks is stubbed (each hook documents what's wired and what isn't). It is **not yet published to npm**.
75
+ `v0.149.0` — pre-publish. The package surface (types, function names, export paths) is the v1 contract; runtime behaviour for some hooks is stubbed (each hook documents what's wired and what isn't). It is **not yet published to npm**.
76
+
77
+ ### What's new in 0.149.0 (contract 1.117.0)
78
+
79
+ **New primitive `<EmojiPicker>` — pick an emoji without leaving for the OS keyboard (sc-8104).** Typed emoji always worked: a plain `<TextInput>` stores and renders them on both hosts, and nothing about that changes. What was missing was an in-app way to *choose* one — for a message composer, or to react to something.
80
+
81
+ ```jsx
82
+ const [open, setOpen] = useState(false);
83
+ const [recents, setRecents] = useState([]);
84
+
85
+ <EmojiPicker
86
+ visible={open}
87
+ recents={recents}
88
+ onRecentsChange={setRecents}
89
+ onRequestClose={() => setOpen(false)}
90
+ onSelect={(char) => {
91
+ const { value } = insertAtCaret(draft, char, selection);
92
+ setDraft(value);
93
+ setOpen(false);
94
+ }}
95
+ />
96
+ ```
97
+
98
+ It presents inside `<Overlay>`, so it escapes the widget's clipping box on both hosts, and ships a curated Unicode set (categories, search, recents) as plain data — no emoji dependency to vet. `onSelect` hands you the character; `recents` / `onRecentsChange` let you persist the picks wherever your widget keeps state. Pair it with `insertAtCaret(value, char, selection)` to land the emoji mid-draft instead of appending it.
99
+
100
+ **Also new: a shared reaction model.** `groupReactions(rows, { typeField, userField, userId })` turns reaction rows into per-emoji pill groups — one row per (target, user, emoji), de-duplicated per user — and `readReactionEmoji(value)` maps a stored value to its emoji, ignoring anything it does not recognise. Widgets storing reactions should group through these rather than rolling their own, so pills behave identically wherever they appear.
76
101
 
77
102
  ### What's new in 0.148.0 (contract 1.116.0)
78
103
 
package/dist/contract.cjs CHANGED
@@ -2079,6 +2079,15 @@ const PRIMITIVES = [
2079
2079
  rnComponent: null,
2080
2080
  docsUrl: null,
2081
2081
  },
2082
+ // sc-8104 — the in-app emoji picker. Typed emoji always worked; what this
2083
+ // replaces is being forced out to the OS keyboard to find one.
2084
+ {
2085
+ name: "EmojiPicker",
2086
+ description:
2087
+ "In-app emoji picker. `<EmojiPicker visible={open} onRequestClose={() => setOpen(false)} onSelect={(char) => insert(char)} recents={recents} onRecentsChange={setRecents} />`. THE way to let an app user pick an emoji without leaving for the OS keyboard — for a message/post composer, and for starting a reaction. It presents inside the SDK `<Overlay>`, so it escapes the clipping box of the widget on both hosts, and it ships a curated Unicode set WITH the SDK (categories, search, recents) so no emoji dependency is needed. Props: `visible` (boolean), `onSelect` (`(char: string) => void`, fired with the chosen emoji character), `onRequestClose` (wire it or the picker cannot be dismissed), `recents` (string[] of previously picked characters) and `onRecentsChange` (persist them where the widget keeps its own state), plus `accessibilityLabel` and `searchPlaceholder`. To insert into a composer at the caret rather than appending, pair it with `insertAtCaret(value, char, selection)`. Typed emoji need nothing: a plain `TextInput` already stores and renders them.",
2088
+ rnComponent: null,
2089
+ docsUrl: null,
2090
+ },
2082
2091
  // sc-6970 — formatted content, rendered. Widgets have no HTML path on either
2083
2092
  // host, so this is the ONE way bold, headings and lists reach a reader.
2084
2093
  {
@@ -4243,7 +4252,15 @@ const CONTRACT = deepFreeze({
4243
4252
  // hosts' shared textStyle module), not a theme token. Additive: no export
4244
4253
  // changed signature, and a theme carrying no `roles` renders on the seeded
4245
4254
  // defaults exactly as before.
4246
- version: "1.117.0",
4255
+ // 1.118.0: additive (sc-8104) — the `EmojiPicker` primitive, plus the emoji
4256
+ // set and reaction model it ships with. Typed emoji always worked; there
4257
+ // was no in-app way to PICK one, so every emoji meant a trip to the OS
4258
+ // keyboard. The curated Unicode set ships as plain string data rather than
4259
+ // a vetted dependency. `groupReactions` / `readReactionEmoji` are shared
4260
+ // because Newsfeed and Chat both render per-emoji pills over a Reactions
4261
+ // table, and the legacy slug mapping (`like` -> emoji) must not be
4262
+ // re-derived per widget.
4263
+ version: "1.118.0",
4247
4264
  sharedTranslationKeys: SHARED_TRANSLATION_KEYS,
4248
4265
  hooks: HOOKS,
4249
4266
  primitives: PRIMITIVES,
package/dist/contract.js CHANGED
@@ -2079,6 +2079,15 @@ const PRIMITIVES = [
2079
2079
  rnComponent: null,
2080
2080
  docsUrl: null,
2081
2081
  },
2082
+ // sc-8104 — the in-app emoji picker. Typed emoji always worked; what this
2083
+ // replaces is being forced out to the OS keyboard to find one.
2084
+ {
2085
+ name: "EmojiPicker",
2086
+ description:
2087
+ "In-app emoji picker. `<EmojiPicker visible={open} onRequestClose={() => setOpen(false)} onSelect={(char) => insert(char)} recents={recents} onRecentsChange={setRecents} />`. THE way to let an app user pick an emoji without leaving for the OS keyboard — for a message/post composer, and for starting a reaction. It presents inside the SDK `<Overlay>`, so it escapes the clipping box of the widget on both hosts, and it ships a curated Unicode set WITH the SDK (categories, search, recents) so no emoji dependency is needed. Props: `visible` (boolean), `onSelect` (`(char: string) => void`, fired with the chosen emoji character), `onRequestClose` (wire it or the picker cannot be dismissed), `recents` (string[] of previously picked characters) and `onRecentsChange` (persist them where the widget keeps its own state), plus `accessibilityLabel` and `searchPlaceholder`. To insert into a composer at the caret rather than appending, pair it with `insertAtCaret(value, char, selection)`. Typed emoji need nothing: a plain `TextInput` already stores and renders them.",
2088
+ rnComponent: null,
2089
+ docsUrl: null,
2090
+ },
2082
2091
  // sc-6970 — formatted content, rendered. Widgets have no HTML path on either
2083
2092
  // host, so this is the ONE way bold, headings and lists reach a reader.
2084
2093
  {
@@ -4239,7 +4248,15 @@ const CONTRACT = deepFreeze({
4239
4248
  // hosts' shared textStyle module), not a theme token. Additive: no export
4240
4249
  // changed signature, and a theme carrying no `roles` renders on the seeded
4241
4250
  // defaults exactly as before.
4242
- version: "1.117.0",
4251
+ // 1.118.0: additive (sc-8104) — the `EmojiPicker` primitive, plus the emoji
4252
+ // set and reaction model it ships with. Typed emoji always worked; there
4253
+ // was no in-app way to PICK one, so every emoji meant a trip to the OS
4254
+ // keyboard. The curated Unicode set ships as plain string data rather than
4255
+ // a vetted dependency. `groupReactions` / `readReactionEmoji` are shared
4256
+ // because Newsfeed and Chat both render per-emoji pills over a Reactions
4257
+ // table, and the legacy slug mapping (`like` -> emoji) must not be
4258
+ // re-derived per widget.
4259
+ version: "1.118.0",
4243
4260
  sharedTranslationKeys: SHARED_TRANSLATION_KEYS,
4244
4261
  hooks: HOOKS,
4245
4262
  primitives: PRIMITIVES,