Skip to content

Commit 2959580

Browse files
authored
Merge branch 'main' into react-native-sdk-client-header
2 parents b4da8dd + 716518b commit 2959580

15 files changed

Lines changed: 273 additions & 69 deletions

File tree

.github/workflows/publish.yml

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,6 @@ on:
55
branches:
66
- main
77

8-
permissions:
9-
id-token: write # Required publishing to npm using OIDC
10-
contents: read
11-
128
jobs:
139
release:
1410
runs-on: ubuntu-latest
@@ -20,27 +16,30 @@ jobs:
2016
# Setup .npmrc file to publish to npm
2117
- name: Enable corepack
2218
run: corepack enable
23-
- uses: actions/setup-node@v4
19+
- uses: actions/setup-node@v6
2420
with:
2521
node-version-file: ".nvmrc"
2622
cache: "yarn"
2723
cache-dependency-path: "**/yarn.lock"
2824
registry-url: "https://registry.npmjs.org"
2925
scope: "@reflag"
30-
- name: update npm - remove this once we upgrade Node.js
31-
run: npm install -g npm@11.8.0
32-
- name: npm version
33-
run: npm version
3426
- name: Install dependencies
3527
run: yarn install --immutable
3628
- name: Build packages
3729
run: yarn build
3830
- name: Publish
39-
run: yarn lerna publish from-package --no-private --yes
40-
env:
41-
NODE_AUTH_TOKEN: ""
42-
NPM_CONFIG_PROVENANCE: "true"
43-
NPM_CONFIG_ACCESS: "public"
31+
run: |
32+
yarn lerna list --since --parseable --no-private | while read -r pkg; do
33+
name=$(node -p "require('$pkg/package.json').name")
34+
version=$(node -p "require('$pkg/package.json').version")
35+
published=$(npm view "$name" version --json 2>/dev/null || echo "")
36+
if [ "$published" = "\"$version\"" ]; then
37+
echo "SKIP $name@$version"
38+
else
39+
echo "PUBLISH $name@$version (registry has $published)"
40+
(cd "$pkg" && npm publish --access public --provenance)
41+
fi
42+
done
4443
- name: Build docs
4544
run: yarn docs
4645
- name: Checkout docs with SSH

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,12 @@ Client side React SDK
88

99
[Read the docs](packages/react-sdk/README.md)
1010

11+
## React Native SDK (beta)
12+
13+
React Native SDK for mobile apps
14+
15+
[Read the docs](packages/react-native-sdk/README.md)
16+
1117
## Vue SDK (beta)
1218

1319
Client side Vue SDK

packages/browser-sdk/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@reflag/browser-sdk",
3-
"version": "1.4.0",
3+
"version": "1.4.1",
44
"packageManager": "yarn@4.1.1",
55
"license": "MIT",
66
"repository": {

packages/browser-sdk/src/feedback/ui/FeedbackDialog.css

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
.dialog {
22
position: fixed;
33
width: 210px;
4+
overflow: visible;
45
padding: 16px 22px 10px;
56
font-size: var(--reflag-feedback-dialog-font-size, 1rem);
67
font-family: var(

packages/browser-sdk/src/feedback/ui/index.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,14 @@ export const DEFAULT_POSITION: Position = {
1111
placement: "bottom-right",
1212
};
1313

14+
function supportsPopoverApi() {
15+
return (
16+
typeof HTMLElement !== "undefined" &&
17+
"showPopover" in HTMLElement.prototype &&
18+
"hidePopover" in HTMLElement.prototype
19+
);
20+
}
21+
1422
function stopPropagation(e: Event) {
1523
e.stopPropagation();
1624
}
@@ -39,9 +47,18 @@ function attachDialogContainer() {
3947
let openInstances = 0;
4048

4149
export function openFeedbackForm(options: OpenFeedbackFormOptions): void {
42-
const shadowRoot = attachDialogContainer();
4350
const position = options.position || DEFAULT_POSITION;
4451

52+
if (position.type !== "MODAL" && !supportsPopoverApi()) {
53+
console.warn(
54+
"[Reflag]",
55+
"Unable to open feedback popup. Popover API is not supported in this browser",
56+
);
57+
return;
58+
}
59+
60+
const shadowRoot = attachDialogContainer();
61+
4562
if (position.type === "POPOVER") {
4663
if (!position.anchor) {
4764
console.warn(

packages/browser-sdk/src/ui/Dialog.css

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
margin: auto;
4343
margin-top: 4rem;
4444

45-
&[open] {
45+
&.open {
4646
animation: /* easeOutQuint */
4747
scale 100ms cubic-bezier(0.22, 1, 0.36, 1),
4848
fade 100ms cubic-bezier(0.22, 1, 0.36, 1);
@@ -59,7 +59,7 @@
5959
position: absolute;
6060
margin: 0;
6161

62-
&[open] {
62+
&.open {
6363
animation: /* easeOutQuint */
6464
scale 100ms cubic-bezier(0.22, 1, 0.36, 1),
6565
fade 100ms cubic-bezier(0.22, 1, 0.36, 1);
@@ -92,7 +92,7 @@
9292

9393
/* Unanchored */
9494

95-
.dialog[open].unanchored {
95+
.dialog.open.unanchored {
9696
&.unanchored-bottom-left,
9797
&.unanchored-bottom-right {
9898
animation: /* easeOutQuint */

packages/browser-sdk/src/ui/Dialog.tsx

Lines changed: 73 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ export const Dialog: FunctionComponent<OpenDialogOptions> = ({
8181
showArrow = true,
8282
}) => {
8383
const arrowRef = useRef<HTMLDivElement>(null);
84-
const dialogRef = useRef<HTMLDialogElement>(null);
84+
const dialogRef = useRef<HTMLElement>(null);
8585

8686
const anchor = position.type === "POPOVER" ? position.anchor : null;
8787
const placement =
@@ -173,23 +173,56 @@ export const Dialog: FunctionComponent<OpenDialogOptions> = ({
173173
// eslint-disable-next-line react-hooks/exhaustive-deps -- anchor only exists in popover
174174
}, [position.type, close, (position as any).anchor, dismiss, containerId]);
175175

176-
function setDiagRef(node: HTMLDialogElement | null) {
176+
function setDiagRef(node: HTMLElement | null) {
177177
refs.setFloating(node);
178178
dialogRef.current = node;
179179
}
180180

181181
useEffect(() => {
182182
if (!dialogRef.current) return;
183-
if (isOpen && !dialogRef.current.hasAttribute("open")) {
184-
dialogRef.current[position.type === "MODAL" ? "showModal" : "show"]();
183+
184+
const isPopoverOpen = () => {
185+
try {
186+
return dialogRef.current?.matches(":popover-open") ?? false;
187+
} catch {
188+
return false;
189+
}
190+
};
191+
192+
const isModalOpen =
193+
dialogRef.current instanceof HTMLDialogElement &&
194+
dialogRef.current.hasAttribute("open");
195+
196+
if (
197+
isOpen &&
198+
((position.type === "MODAL" && !isModalOpen) ||
199+
(position.type !== "MODAL" && !isPopoverOpen()))
200+
) {
201+
if (
202+
position.type === "MODAL" &&
203+
dialogRef.current instanceof HTMLDialogElement
204+
) {
205+
dialogRef.current.showModal();
206+
} else {
207+
dialogRef.current.showPopover();
208+
}
185209
}
186-
if (!isOpen && dialogRef.current.hasAttribute("open")) {
187-
dialogRef.current.close();
210+
if (!isOpen) {
211+
if (
212+
position.type === "MODAL" &&
213+
dialogRef.current instanceof HTMLDialogElement &&
214+
dialogRef.current.hasAttribute("open")
215+
) {
216+
dialogRef.current.close();
217+
} else if (position.type !== "MODAL" && isPopoverOpen()) {
218+
dialogRef.current.hidePopover();
219+
}
188220
}
189221
}, [dialogRef, isOpen, position.type]);
190222

191223
const classes = [
192224
"dialog",
225+
isOpen ? "open" : "",
193226
position.type === "MODAL"
194227
? "modal"
195228
: position.type === "POPOVER"
@@ -201,21 +234,40 @@ export const Dialog: FunctionComponent<OpenDialogOptions> = ({
201234
return (
202235
<>
203236
<style dangerouslySetInnerHTML={{ __html: styles }} />
204-
<dialog
205-
ref={setDiagRef}
206-
class={classes}
207-
style={anchor ? floatingStyles : unanchoredPosition}
208-
>
209-
{children && <Fragment>{children}</Fragment>}
210-
211-
{anchor && showArrow && (
212-
<DialogArrow
213-
arrowData={middlewareData?.arrow}
214-
arrowRef={arrowRef}
215-
placement={actualPlacement}
216-
/>
217-
)}
218-
</dialog>
237+
{position.type === "MODAL" ? (
238+
<dialog
239+
ref={setDiagRef}
240+
class={classes}
241+
style={anchor ? floatingStyles : unanchoredPosition}
242+
>
243+
{children && <Fragment>{children}</Fragment>}
244+
245+
{anchor && showArrow && (
246+
<DialogArrow
247+
arrowData={middlewareData?.arrow}
248+
arrowRef={arrowRef}
249+
placement={actualPlacement}
250+
/>
251+
)}
252+
</dialog>
253+
) : (
254+
<div
255+
ref={setDiagRef}
256+
class={classes}
257+
style={anchor ? floatingStyles : unanchoredPosition}
258+
popover="manual"
259+
>
260+
{children && <Fragment>{children}</Fragment>}
261+
262+
{anchor && showArrow && (
263+
<DialogArrow
264+
arrowData={middlewareData?.arrow}
265+
arrowRef={arrowRef}
266+
placement={actualPlacement}
267+
/>
268+
)}
269+
</div>
270+
)}
219271
</>
220272
);
221273
};

0 commit comments

Comments
 (0)