@flonix/ig-embed 0.0.0-stage → 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 +274 -2
- package/dist/flonix-ig.global.js +211 -0
- package/dist/flonix-ig.global.js.map +1 -0
- package/dist/index.d.mts +199 -0
- package/dist/index.d.ts +199 -0
- package/dist/index.js +1320 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +1313 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +41 -4
package/README.md
CHANGED
|
@@ -1,3 +1,275 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @flonix/ig-embed
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Framework-agnostic, zero-dependency JavaScript widget that lets a host platform's
|
|
4
|
+
end-users connect Instagram and set up **comment / DM automations** — powered by
|
|
5
|
+
Flonix. Built for partner platforms that embed Flonix's Instagram automations for their own users.
|
|
6
|
+
|
|
7
|
+
- Drops into any stack (plain HTML, React, Vue, Svelte, …) — no framework runtime shipped.
|
|
8
|
+
- Renders inside a **Shadow DOM**, so the host's CSS can't break it and its CSS can't leak out.
|
|
9
|
+
- Fully themeable via a **shadcn-style design-token contract** (light + dark) and a custom font.
|
|
10
|
+
- Three screens: **connect → posts (incremental) → automate dialog** (comment/DM, prefilled, with a prefilled follow-gate).
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Install
|
|
15
|
+
|
|
16
|
+
Bundler (React / Vue / Svelte / Angular / …):
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npm install @flonix/ig-embed
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Or drop in the standalone build via a `<script>` tag — no build step, exposes a global `FlonixIG`:
|
|
23
|
+
|
|
24
|
+
```html
|
|
25
|
+
<script src="https://flonix.pro/embed/flonix-ig.global.js"></script>
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## Core API
|
|
31
|
+
|
|
32
|
+
The widget renders into **one DOM element** and runs itself. There are only two calls:
|
|
33
|
+
|
|
34
|
+
```ts
|
|
35
|
+
const instance = FlonixIG.mount(target, config) // render into `target`, returns an instance
|
|
36
|
+
instance.unmount() // tear down + remove its DOM
|
|
37
|
+
instance.refresh() // re-fetch session + posts
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
**When do you call them?** You almost never call them on a click. In a framework, you
|
|
41
|
+
**mount when the component appears** and **unmount when it goes away** — the framework's
|
|
42
|
+
lifecycle drives it. The widget creates its own Shadow root inside `target`, so give it an
|
|
43
|
+
empty element and don't render your own children into it.
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## Framework integration
|
|
48
|
+
|
|
49
|
+
### Plain HTML / `<script>`
|
|
50
|
+
|
|
51
|
+
```html
|
|
52
|
+
<div id="flonix"></div>
|
|
53
|
+
|
|
54
|
+
<script src="https://flonix.pro/embed/flonix-ig.global.js"></script>
|
|
55
|
+
<script>
|
|
56
|
+
FlonixIG.mount("#flonix", {
|
|
57
|
+
apiKey: "flxig.…", // the key Flonix issued you
|
|
58
|
+
user: { id: "merchant_42" }, // your stable id for this merchant
|
|
59
|
+
partner: { // required — shows "<your logo> × flonix"
|
|
60
|
+
name: "Acme",
|
|
61
|
+
logo: "https://acme.com/logo.svg",
|
|
62
|
+
},
|
|
63
|
+
})
|
|
64
|
+
</script>
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Put the `<div>` where you want the widget, then mount once after the script loads. On a static
|
|
68
|
+
page you don't need `unmount()` — the widget is cleaned up when the page unloads.
|
|
69
|
+
|
|
70
|
+
### React
|
|
71
|
+
|
|
72
|
+
```tsx
|
|
73
|
+
import { useEffect, useRef } from "react"
|
|
74
|
+
import { FlonixIG } from "@flonix/ig-embed"
|
|
75
|
+
|
|
76
|
+
export function FlonixInstagram({ apiKey, userId }: { apiKey: string; userId: string }) {
|
|
77
|
+
const ref = useRef<HTMLDivElement>(null)
|
|
78
|
+
|
|
79
|
+
useEffect(() => {
|
|
80
|
+
if (!ref.current) return
|
|
81
|
+
// effect runs AFTER the <div> is in the DOM → safe to mount
|
|
82
|
+
const instance = FlonixIG.mount(ref.current, {
|
|
83
|
+
apiKey,
|
|
84
|
+
user: { id: userId },
|
|
85
|
+
partner: { name: "Acme", logo: "https://acme.com/logo.svg" },
|
|
86
|
+
theme: { mode: "auto" },
|
|
87
|
+
})
|
|
88
|
+
// cleanup runs on unmount, or before re-running when deps change
|
|
89
|
+
return () => instance.unmount()
|
|
90
|
+
}, [apiKey, userId])
|
|
91
|
+
|
|
92
|
+
return <div ref={ref} />
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Render `<FlonixInstagram apiKey={orgKey} userId={merchant.id} />` wherever the merchant should
|
|
97
|
+
connect. Mount fires when the component first appears; unmount fires when it leaves the screen.
|
|
98
|
+
The `[apiKey, userId]` deps remount a fresh widget if the merchant changes, and the cleanup keeps
|
|
99
|
+
it safe under React **StrictMode** (which runs effects twice in dev).
|
|
100
|
+
|
|
101
|
+
### Vue 3 (`<script setup>`)
|
|
102
|
+
|
|
103
|
+
```vue
|
|
104
|
+
<script setup lang="ts">
|
|
105
|
+
import { onMounted, onBeforeUnmount, ref } from "vue"
|
|
106
|
+
import { FlonixIG, type FlonixIGInstance } from "@flonix/ig-embed"
|
|
107
|
+
|
|
108
|
+
const props = defineProps<{ apiKey: string; userId: string }>()
|
|
109
|
+
const el = ref<HTMLDivElement | null>(null)
|
|
110
|
+
let instance: FlonixIGInstance | null = null
|
|
111
|
+
|
|
112
|
+
onMounted(() => {
|
|
113
|
+
if (!el.value) return
|
|
114
|
+
instance = FlonixIG.mount(el.value, {
|
|
115
|
+
apiKey: props.apiKey,
|
|
116
|
+
user: { id: props.userId },
|
|
117
|
+
partner: { name: "Acme", logo: "https://acme.com/logo.svg" },
|
|
118
|
+
theme: { mode: "auto" },
|
|
119
|
+
})
|
|
120
|
+
})
|
|
121
|
+
|
|
122
|
+
onBeforeUnmount(() => instance?.unmount())
|
|
123
|
+
</script>
|
|
124
|
+
|
|
125
|
+
<template>
|
|
126
|
+
<div ref="el"></div>
|
|
127
|
+
</template>
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
`onMounted` runs once the template node exists → mount there. `onBeforeUnmount` tears it down when
|
|
131
|
+
the component is removed.
|
|
132
|
+
|
|
133
|
+
### Svelte (5)
|
|
134
|
+
|
|
135
|
+
```svelte
|
|
136
|
+
<script lang="ts">
|
|
137
|
+
import { onMount } from "svelte"
|
|
138
|
+
import { FlonixIG } from "@flonix/ig-embed"
|
|
139
|
+
|
|
140
|
+
let { apiKey, userId }: { apiKey: string; userId: string } = $props()
|
|
141
|
+
let el: HTMLDivElement
|
|
142
|
+
|
|
143
|
+
onMount(() => {
|
|
144
|
+
const instance = FlonixIG.mount(el, {
|
|
145
|
+
apiKey,
|
|
146
|
+
user: { id: userId },
|
|
147
|
+
partner: { name: "Acme", logo: "https://acme.com/logo.svg" },
|
|
148
|
+
theme: { mode: "auto" },
|
|
149
|
+
})
|
|
150
|
+
// a function returned from onMount runs on destroy → unmount
|
|
151
|
+
return () => instance.unmount()
|
|
152
|
+
})
|
|
153
|
+
</script>
|
|
154
|
+
|
|
155
|
+
<div bind:this={el}></div>
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
`onMount` runs after the DOM is ready, and the function it returns runs on destroy — so mount and
|
|
159
|
+
unmount line up with the component's life. *(Svelte 4: replace `$props()` with
|
|
160
|
+
`export let apiKey; export let userId;`.)*
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
## Configuration
|
|
165
|
+
|
|
166
|
+
| Option | Type | Default | Notes |
|
|
167
|
+
|---|---|---|---|
|
|
168
|
+
| `apiKey` | `string` | — | **Required.** Org API key from the Flonix admin dashboard. |
|
|
169
|
+
| `user.id` | `string` | — | **Required.** Stable id for the end-user (merchant) in your platform. |
|
|
170
|
+
| `user.email` / `user.name` | `string` | — | Optional metadata. |
|
|
171
|
+
| `partner.name` | `string` | — | **Required.** Your brand name — used as the logo's alt text. |
|
|
172
|
+
| `partner.logo` | `string` | — | **Required.** Your logo (light theme). Any image URL or data URI. See **Partner logo**. |
|
|
173
|
+
| `partner.logoDark` | `string` | `partner.logo` | Optional logo variant for dark theme. |
|
|
174
|
+
| `baseUrl` | `string` | `https://flonix.pro` | Flonix API origin. |
|
|
175
|
+
| `returnUrl` | `string` | current URL | Where Instagram OAuth returns to. |
|
|
176
|
+
| `theme` | `ThemeConfig` | Flonix defaults | See **Theming** below. |
|
|
177
|
+
| `onConnected(account)` | fn | — | Fired once Instagram is connected. |
|
|
178
|
+
| `onAutomationCreated(a)` | fn | — | Fired after an automation is created. |
|
|
179
|
+
| `onError(err)` | fn | — | Fired on any load/flow error. |
|
|
180
|
+
|
|
181
|
+
The instance exposes `refresh()` and `unmount()`.
|
|
182
|
+
|
|
183
|
+
---
|
|
184
|
+
|
|
185
|
+
## Partner logo
|
|
186
|
+
|
|
187
|
+
`partner` is **required** — the widget renders your logo next to the Flonix mark as
|
|
188
|
+
**`<your logo> × flonix`** (bottom of the connect screen).
|
|
189
|
+
|
|
190
|
+
```ts
|
|
191
|
+
FlonixIG.mount("#flonix", {
|
|
192
|
+
apiKey, user,
|
|
193
|
+
partner: {
|
|
194
|
+
name: "Acme", // alt text (required)
|
|
195
|
+
logo: "https://acme.com/logo.svg", // light theme (required)
|
|
196
|
+
logoDark: "https://acme.com/logo-white.svg", // dark theme (optional)
|
|
197
|
+
},
|
|
198
|
+
})
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
- **Format:** any image — an `https` URL or a `data:` URI — in any format (**SVG, PNG, WebP**).
|
|
202
|
+
Transparent background strongly recommended.
|
|
203
|
+
- **Expected size:** the logo is displayed at **18px height, width auto (capped at 120px)**.
|
|
204
|
+
Supply the asset at roughly **2× (≈40px tall)** — or an **SVG** — so it stays crisp on
|
|
205
|
+
high-DPI screens. A horizontal wordmark or a square icon both work.
|
|
206
|
+
- **Light vs dark:** provide `logoDark` if your logo needs a different version on dark
|
|
207
|
+
backgrounds; otherwise `logo` is used for both themes.
|
|
208
|
+
|
|
209
|
+
---
|
|
210
|
+
|
|
211
|
+
## Theming
|
|
212
|
+
|
|
213
|
+
Pass Flonix a subset of tokens per mode — anything omitted falls back to Flonix defaults.
|
|
214
|
+
|
|
215
|
+
```ts
|
|
216
|
+
FlonixIG.mount("#flonix", {
|
|
217
|
+
apiKey, user,
|
|
218
|
+
theme: {
|
|
219
|
+
mode: "auto", // "light" | "dark" | "auto" (default: auto)
|
|
220
|
+
fontFamily: '"Inter", system-ui, sans-serif',
|
|
221
|
+
radius: "12px",
|
|
222
|
+
tokens: {
|
|
223
|
+
light: { primary: "#16a34a", primaryForeground: "#ffffff", ring: "#16a34a" },
|
|
224
|
+
dark: { primary: "#22c55e", primaryForeground: "#052e16", ring: "#22c55e" },
|
|
225
|
+
},
|
|
226
|
+
},
|
|
227
|
+
})
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
**Token names** (shadcn-style, each a raw CSS color string):
|
|
231
|
+
|
|
232
|
+
`background` · `foreground` · `card` · `cardForeground` · `popover` · `popoverForeground` ·
|
|
233
|
+
`primary` · `primaryForeground` · `secondary` · `secondaryForeground` · `muted` ·
|
|
234
|
+
`mutedForeground` · `accent` · `accentForeground` · `destructive` · `destructiveForeground` ·
|
|
235
|
+
`border` · `input` · `ring`
|
|
236
|
+
|
|
237
|
+
Internally these become `--flxig-*` CSS custom properties on the Shadow root's
|
|
238
|
+
`:host` (light) and `:host(.flxig-dark)` (dark). In `auto` mode the widget follows
|
|
239
|
+
the host's `prefers-color-scheme` and reacts to live changes.
|
|
240
|
+
|
|
241
|
+
---
|
|
242
|
+
|
|
243
|
+
## Flow
|
|
244
|
+
|
|
245
|
+
1. **Connect** — empty state; the user clicks *Connect Instagram* and is redirected to
|
|
246
|
+
Flonix auth → Instagram OAuth. On return the widget detects the connection.
|
|
247
|
+
2. **Posts** — the connected account's media, loaded incrementally as you scroll.
|
|
248
|
+
3. **Automate** — each post has an *Automate* button opening a dialog with **Comment** and
|
|
249
|
+
**DM** options; every field (including the follow-gate) comes prefilled.
|
|
250
|
+
|
|
251
|
+
---
|
|
252
|
+
|
|
253
|
+
## Local development
|
|
254
|
+
|
|
255
|
+
```bash
|
|
256
|
+
pnpm --filter @flonix/ig-embed build # emit dist/ (ESM + CJS + IIFE + d.ts)
|
|
257
|
+
pnpm --filter @flonix/ig-embed dev # build + serve the demo at http://localhost:4321
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
The demo (`demo/index.html`) runs against `createMockTransport()` — no backend needed —
|
|
261
|
+
and includes live controls for theme mode, custom brand tokens, and font.
|
|
262
|
+
|
|
263
|
+
---
|
|
264
|
+
|
|
265
|
+
## API contract (backend)
|
|
266
|
+
|
|
267
|
+
The widget talks to these Flonix endpoints (all under `baseUrl`):
|
|
268
|
+
|
|
269
|
+
| Method | Path | Auth | Purpose |
|
|
270
|
+
|---|---|---|---|
|
|
271
|
+
| `POST` | `/api/embed/session` | `apiKey` | Resolve/create the end-user, return a session token + connection status. |
|
|
272
|
+
| `POST` | `/api/embed/connect/start` | Bearer session | Return the Instagram OAuth authorize URL. |
|
|
273
|
+
| `GET` | `/api/embed/connect/callback` | OAuth state | Store the connection, redirect back to `returnUrl`. |
|
|
274
|
+
| `GET` | `/api/embed/posts?cursor=` | Bearer session | Return a page of posts + `nextCursor`. |
|
|
275
|
+
| `POST` | `/api/embed/automations` | Bearer session | Create a comment/DM automation. |
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
"use strict";var FlonixIG=(()=>{var S=Object.defineProperty;var xe=Object.getOwnPropertyDescriptor;var he=Object.getOwnPropertyNames;var be=Object.prototype.hasOwnProperty;var ve=(e,t)=>{for(var n in t)S(e,n,{get:t[n],enumerable:!0})},ye=(e,t,n,i)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of he(t))!be.call(e,o)&&o!==n&&S(e,o,{get:()=>t[o],enumerable:!(i=xe(t,o))||i.enumerable});return e};var we=e=>ye(S({},"__esModule",{value:!0}),e);var Ne={};ve(Ne,{DEFAULT_TOKENS:()=>E,FlonixIG:()=>fe,createHttpTransport:()=>k,createMockTransport:()=>K,mount:()=>R,version:()=>z});var J="data:image/png;base64,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";function N(e){return e.replace(/[&<>"']/g,t=>t==="&"?"&":t==="<"?"<":t===">"?">":t==='"'?""":"'")}var Ae="Inter, ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif";function D(e=20){return`<span class="flxig-brand" style="--flxig-logo-size:${e}px" role="img" aria-label="Flonix">
|
|
2
|
+
<span class="flxig-brand__chip">
|
|
3
|
+
<img class="flxig-brand__img" src="${J}" alt="" draggable="false" />
|
|
4
|
+
</span>
|
|
5
|
+
<svg class="flxig-brand__wordmark" viewBox="0 0 55 22" fill="currentColor" aria-hidden="true">
|
|
6
|
+
<text x="0" y="19" font-size="22" font-weight="700" letter-spacing="-0.4" font-family="${Ae}" textLength="55" lengthAdjust="spacingAndGlyphs">flonix</text>
|
|
7
|
+
</svg>
|
|
8
|
+
</span>`}function q(e){let t=N(e.name),n=N(e.logo),i=e.logoDark?N(e.logoDark):"",o=i?`<img class="flxig-partner__img flxig-partner__img--light" src="${n}" alt="${t}" draggable="false" />
|
|
9
|
+
<img class="flxig-partner__img flxig-partner__img--dark" src="${i}" alt="${t}" draggable="false" />`:`<img class="flxig-partner__img" src="${n}" alt="${t}" draggable="false" />`;return`<span class="flxig-cobrand">
|
|
10
|
+
<span class="flxig-partner" data-has-dark="${i?"true":"false"}">${o}</span>
|
|
11
|
+
<span class="flxig-cobrand__x">\xD7</span>
|
|
12
|
+
${D(18)}
|
|
13
|
+
</span>`}var s={instagram:(e=18)=>`<svg width="${e}" height="${e}" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
|
14
|
+
<rect x="2" y="2" width="20" height="20" rx="5" ry="5"/>
|
|
15
|
+
<path d="M16 11.37A4 4 0 1 1 12.63 8 4 4 0 0 1 16 11.37z"/>
|
|
16
|
+
<line x1="17.5" y1="6.5" x2="17.51" y2="6.5"/>
|
|
17
|
+
</svg>`,comment:(e=18)=>`<svg width="${e}" height="${e}" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
|
18
|
+
<path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z"/>
|
|
19
|
+
</svg>`,dm:(e=18)=>`<svg width="${e}" height="${e}" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
|
20
|
+
<line x1="22" y1="2" x2="11" y2="13"/>
|
|
21
|
+
<polygon points="22 2 15 22 11 13 2 9 22 2"/>
|
|
22
|
+
</svg>`,check:(e=16)=>`<svg width="${e}" height="${e}" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
|
23
|
+
<polyline points="20 6 9 17 4 12"/>
|
|
24
|
+
</svg>`,close:(e=18)=>`<svg width="${e}" height="${e}" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
|
25
|
+
<line x1="18" y1="6" x2="6" y2="18"/>
|
|
26
|
+
<line x1="6" y1="6" x2="18" y2="18"/>
|
|
27
|
+
</svg>`,plus:(e=16)=>`<svg width="${e}" height="${e}" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
|
28
|
+
<line x1="12" y1="5" x2="12" y2="19"/>
|
|
29
|
+
<line x1="5" y1="12" x2="19" y2="12"/>
|
|
30
|
+
</svg>`,link:(e=15)=>`<svg width="${e}" height="${e}" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
|
31
|
+
<path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/>
|
|
32
|
+
<path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/>
|
|
33
|
+
</svg>`,bolt:(e=16)=>`<svg width="${e}" height="${e}" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
|
|
34
|
+
<path d="M13 2 4.5 13.5H11L10 22l8.5-11.5H12L13 2Z"/>
|
|
35
|
+
</svg>`,spinner:(e=18)=>`<svg class="flxig-spin" width="${e}" height="${e}" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" aria-hidden="true">
|
|
36
|
+
<path d="M21 12a9 9 0 1 1-6.219-8.56"/>
|
|
37
|
+
</svg>`,video:(e=14)=>`<svg width="${e}" height="${e}" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
|
|
38
|
+
<path d="M8 5v14l11-7L8 5Z"/>
|
|
39
|
+
</svg>`,layers:(e=14)=>`<svg width="${e}" height="${e}" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
|
40
|
+
<polygon points="12 2 2 7 12 12 22 7 12 2"/>
|
|
41
|
+
<polyline points="2 17 12 22 22 17"/>
|
|
42
|
+
<polyline points="2 12 12 17 22 12"/>
|
|
43
|
+
</svg>`};function I(e){return{"Content-Type":"application/json",Authorization:`Bearer ${e}`}}function k(e){let t=e.replace(/\/+$/,"");async function n(i,o){let a;try{a=await fetch(`${t}${i}`,o)}catch{throw new Error("Network error \u2014 please try again.")}let d=await a.json().catch(()=>null);if(!a.ok)throw new Error((d==null?void 0:d.error)||`Request failed (${a.status})`);return d}return{session:({apiKey:i,user:o})=>n("/api/embed/session",{method:"POST",headers:I(i),body:JSON.stringify({user:o})}),connectStart:({token:i,returnUrl:o})=>n("/api/embed/connect/start",{method:"POST",headers:I(i),body:JSON.stringify({returnUrl:o})}),posts:({token:i,cursor:o})=>n(`/api/embed/posts${o?`?cursor=${encodeURIComponent(o)}`:""}`,{method:"GET",headers:I(i)}),createAutomation:({token:i,data:o})=>n("/api/embed/automations",{method:"POST",headers:I(i),body:JSON.stringify(o)})}}function r(e,t={},...n){let i=document.createElement(e);if(t.class&&(i.className=t.class),t.text!=null&&(i.textContent=t.text),t.html!=null&&(i.innerHTML=t.html),t.style&&i.setAttribute("style",t.style),t.dataset)for(let[o,a]of Object.entries(t.dataset))i.dataset[o]=a;if(t.attrs)for(let[o,a]of Object.entries(t.attrs))a==null||a===!1||i.setAttribute(o,a===!0?"":String(a));if(t.on)for(let[o,a]of Object.entries(t.on))i.addEventListener(o,a);return m(i,n),i}function m(e,t){for(let n of t)n==null||n===!1||e.appendChild(n instanceof Node?n:document.createTextNode(String(n)))}function M(e){for(;e.firstChild;)e.removeChild(e.firstChild)}function f(e){var n;let t=document.createElement("div");return t.innerHTML=e.trim(),(n=t.firstElementChild)!=null?n:t}function v(e){var i;let t=["flxig-btn",`flxig-btn--${(i=e.variant)!=null?i:"primary"}`,e.block?"flxig-btn--block":"",e.large?"flxig-btn--lg":""].filter(Boolean).join(" "),n=r("button",{class:t,attrs:{type:"button",disabled:e.disabled},on:e.onClick?{click:e.onClick}:void 0});return e.icon&&n.appendChild(f(e.icon)),m(n,[r("span",{text:e.label})]),n}function b(e,t,n){return r("div",{class:"flxig-field"},r("span",{class:"flxig-label",text:e}),t,n?r("span",{class:"flxig-hint",text:n}):null)}function w(e){var t,n;return r("input",{class:"flxig-input",attrs:{type:"text",value:(t=e.value)!=null?t:"",placeholder:(n=e.placeholder)!=null?n:""}})}function G(e){var n,i,o;let t=r("textarea",{class:"flxig-textarea",attrs:{placeholder:(n=e.placeholder)!=null?n:"",rows:(i=e.rows)!=null?i:3}});return t.value=(o=e.value)!=null?o:"",t}function _(e){let t=r("input",{attrs:{type:"checkbox"}});return t.checked=e.checked,e.onChange&&t.addEventListener("change",()=>e.onChange(t.checked)),{element:r("span",{class:"flxig-switch"},t,r("span",{class:"flxig-switch__track"}),r("span",{class:"flxig-switch__thumb"})),input:t}}function $(e){var d;let t=[...e.values],n=r("span",{class:"flxig-chips"}),i=r("input",{attrs:{type:"text",placeholder:(d=e.placeholder)!=null?d:"Add keyword\u2026"}}),o=()=>{for(;n.firstChild&&n.firstChild!==i;)n.removeChild(n.firstChild);let l=t.map((c,u)=>r("span",{class:"flxig-chip"},r("span",{text:c}),r("button",{attrs:{type:"button","aria-label":`Remove ${c}`},html:s.close(12),on:{click:()=>{t.splice(u,1),o()}}})));n.prepend(...l)},a=()=>{let l=i.value.trim().replace(/,$/,"").trim();l&&!t.includes(l)&&(t.push(l),o()),i.value=""};return i.addEventListener("keydown",l=>{l.key==="Enter"||l.key===","?(l.preventDefault(),a()):l.key==="Backspace"&&!i.value&&t.length&&(t.pop(),o())}),i.addEventListener("blur",a),n.appendChild(i),o(),{element:n,getValues:()=>[...t]}}function ee(e){let t=r("div",{class:"flxig-links"}),n=v({label:"Add link",variant:"ghost",icon:s.plus(15),onClick:()=>{t.querySelectorAll(".flxig-link").length>=e.max||(o({label:"",url:""}),i())}});n.classList.add("flxig-links__add");function i(){n.disabled=t.querySelectorAll(".flxig-link").length>=e.max}function o(l){let c=w({value:l.label,placeholder:"Button label"});c.classList.add("flxig-link__label");let u=r("input",{class:"flxig-input flxig-link__url",attrs:{type:"url",value:l.url,placeholder:"https://\u2026",inputmode:"url"}}),x=r("div",{class:"flxig-link"},f(`<span class="flxig-link__ic">${s.link(15)}</span>`),r("div",{class:"flxig-link__inputs"},c,u),r("button",{class:"flxig-iconbtn",attrs:{type:"button","aria-label":"Remove link"},html:s.close(16),on:{click:()=>{x.remove(),i()}}}));t.appendChild(x)}return(e.values.length?e.values:[{label:"",url:""}]).slice(0,e.max).forEach(o),i(),{element:r("div",{class:"flxig-links__wrap"},t,n),getValues:()=>[...t.querySelectorAll(".flxig-link")].map(l=>({label:l.querySelector(".flxig-link__label").value.trim(),url:l.querySelector(".flxig-link__url").value.trim()})).filter(l=>l.label||l.url)}}function C(e){var t;return r("div",{class:"flxig-state"},e.icon?f(e.icon):null,r("p",{class:"flxig-h2",text:e.title}),e.detail?r("p",{class:"flxig-muted",text:e.detail}):null,(t=e.action)!=null?t:null)}function te(e){let t=v({label:e.connecting?"Redirecting\u2026":"Connect Instagram",variant:"primary",large:!0,block:!0,disabled:e.connecting,icon:e.connecting?s.spinner():s.instagram(),onClick:e.onConnect});return r("div",{class:"flxig-connect"},r("div",{class:"flxig-connect__copy"},r("h1",{class:"flxig-h1",text:"Connect your Instagram with Flonix"}),r("p",{class:"flxig-muted",text:"Link your Instagram account to set up comment and DM automations on your posts \u2014 directly from here."})),r("div",{class:"flxig-connect__cta"},t),f(`<div class="flxig-connect__foot">${q(e.partner)}</div>`))}var ne={IMAGE:{label:"Image",icon:s.instagram(12)},VIDEO:{label:"Video",icon:s.video()},REELS:{label:"Reel",icon:s.video()},CAROUSEL:{label:"Album",icon:s.layers()}};function ke(e,t){var o,a,d;let n=(o=ne[e.mediaType])!=null?o:ne.IMAGE,i=r("div",{class:"flxig-tile__media"});return e.media?m(i,[r("img",{attrs:{src:e.media,alt:(a=e.caption)!=null?a:"Instagram post",loading:"lazy"}})]):m(i,[f(`<div class="flxig-tile__ph">${s.instagram(28)}</div>`)]),m(i,[f(`<span class="flxig-tile__type">${n.icon}<span>${n.label}</span></span>`)]),r("div",{class:"flxig-tile"},i,r("div",{class:"flxig-tile__body"},r("p",{class:"flxig-tile__cap",text:((d=e.caption)==null?void 0:d.trim())||"No caption"}),v({label:"Automate",variant:"secondary",block:!0,icon:s.bolt(),onClick:()=>t(e)})))}function ie(e){var T;let t=(T=e.account)==null?void 0:T.username,n=r("div",{class:"flxig-grid"}),i=r("div",{class:"flxig-sentinel"}),o=r("div",{class:"flxig-loadmore"}),a=r("div",{class:"flxig-header"},r("div",{class:"flxig-header__id"},f(`<span class="flxig-avatar">${s.instagram(18)}</span>`),r("div",{},r("div",{class:"flxig-h2",text:t?`@${t}`:"Instagram"}),r("div",{class:"flxig-muted",text:"Pick a post to automate"}))),f(`<span class="flxig-badge">${s.check(13)}<span>Connected</span></span>`)),d=f(`<div class="flxig-attrib"><span>Automations by</span>${D(15)}</div>`),l=r("div",{},a,n,o,i,d),c=!0,u=!1,x=!1,p=typeof IntersectionObserver!="undefined"?new IntersectionObserver(h=>{h.some(g=>g.isIntersecting)&&c&&!u&&!x&&e.onLoadMore()},{rootMargin:"240px"}):null;p==null||p.observe(i);let y=()=>{M(o),u?m(o,[f(s.spinner(20))]):c&&!p&&m(o,[v({label:"Load more",variant:"ghost",onClick:e.onLoadMore})])};return{element:l,appendPosts(h){x=!1,m(n,h.map(g=>ke(g,e.onAutomate)))},setLoadingMore(h){u=h,y()},setHasMore(h){c=h,y(),h||p==null||p.disconnect()},showEmpty(){x=!0,c=!1,p==null||p.disconnect(),M(n),n.replaceWith(C({icon:s.instagram(30),title:"No posts yet",detail:"Publish a post on Instagram, then come back to automate it."}))},destroy(){p==null||p.disconnect()}}}function Me(e){return e!=null&&e.username?`https://instagram.com/${e.username}`:"https://instagram.com/"}function U(e,t,n){let i=t!=null&&t.username?`@${t.username}`:"us",o={postId:e.id,type:n,entryButtonLabel:"Send me the link",deliveryMessage:"Thanks for reaching out! \u{1F64C} Here's the link you asked for \u{1F447}",linkButtons:[{label:"Shop now",url:""}],followGate:{enabled:!0,followProfileUrl:Me(t),followButtonLabel:`Follow ${i}`,followConfirmButtonLabel:"I'm following \u2705",followUpMessage:"Awesome \u2014 thanks for following! \u{1F499} Here's your link \u{1F447}"}};return n==="COMMENT"?{...o,name:"Comment \u2192 DM automation",keywords:["link","price","info"],commentReply:"Just sent you a DM! \u{1F4E9}"}:{...o,name:"DM keyword automation",keywords:["link","info"],commentReply:null}}var Ee=[{type:"COMMENT",title:"Comment automation",detail:"Reply + DM when someone comments a keyword",icon:s.comment(20)},{type:"DM",title:"DM automation",detail:"Auto-reply when someone DMs a keyword",icon:s.dm(20)}];function oe(e){var h;let t="COMMENT",n=U(e.post,e.account,t),i=!1,o=r("div",{class:"flxig-dialog__body"}),a=r("div",{class:"flxig-overlay"}),d=()=>{document.removeEventListener("keydown",l),a.remove()},l=g=>{g.key==="Escape"&&!i&&d()};document.addEventListener("keydown",l),a.addEventListener("click",g=>{g.target===a&&!i&&d()});let c=r("div",{class:"flxig-seg"}),u=()=>{c.replaceChildren(...Ee.map(g=>r("div",{class:"flxig-seg__opt",dataset:{active:String(g.type===t)},attrs:{role:"button",tabindex:"0"},on:{click:()=>{g.type!==t&&(t=g.type,n=U(e.post,e.account,t),u(),p())}}},f(`<span class="flxig-seg__ic">${g.icon}</span>`),r("div",{},r("div",{class:"flxig-seg__t",text:g.title}),r("div",{class:"flxig-seg__d",text:g.detail})))))},x=()=>n,p=()=>{var Y;let g=$({values:n.keywords,placeholder:"Add keyword\u2026"}),A=w({value:(Y=n.commentReply)!=null?Y:""}),Q=G({value:n.deliveryMessage,rows:3}),F=w({value:n.entryButtonLabel}),H=ee({values:n.linkButtons,max:3}),O=G({value:n.followGate.followUpMessage,rows:2}),V=w({value:n.followGate.followButtonLabel}),j=w({value:n.followGate.followProfileUrl}),X=w({value:n.followGate.followConfirmButtonLabel}),Z=r("div",{class:"flxig-gate__fields",dataset:{off:String(!n.followGate.enabled)}},b("Follow profile URL",j),b("Follow button label",V),b("Confirm button label",X),b("Message after they follow",O)),W=_({checked:n.followGate.enabled,onChange:me=>{Z.dataset.off=String(!me)}}),ue=r("div",{class:"flxig-gate"},r("div",{class:"flxig-gate__top"},r("div",{},r("div",{class:"flxig-label",text:"Follow gate"}),r("div",{class:"flxig-hint",text:"Require users to follow before they get the link."})),W.element),Z),B=[b(t==="COMMENT"?"Trigger keywords (in comments)":"Trigger keywords (in DMs)",g.element,"Press Enter or comma to add. The automation fires on these words.")];t==="COMMENT"&&B.push(b("Public comment reply",A,"Posted under the comment.")),B.push(b("DM message",Q,"The direct message delivered to the user."),b("Link buttons",H.element,`Where they enter the link(s). Up to ${3} \u2014 each has a label and a URL.`),b("Opt-in button label",F,"Button users tap in the first DM."),ue),o.replaceChildren(...B),x=()=>({postId:e.post.id,type:t,name:n.name,keywords:g.getValues(),commentReply:t==="COMMENT"&&A.value.trim()||null,entryButtonLabel:F.value.trim(),deliveryMessage:Q.value.trim(),linkButtons:H.getValues(),followGate:{enabled:W.input.checked,followProfileUrl:j.value.trim(),followButtonLabel:V.value.trim(),followConfirmButtonLabel:X.value.trim(),followUpMessage:O.value.trim()}}),o.prepend(r("div",{class:"flxig-field"},r("span",{class:"flxig-label",text:"Automation type"}),c))},y=v({label:"Create automation",variant:"primary",icon:s.bolt(),onClick:async()=>{if(i)return;let g=x();if(!g.keywords.length){e.onToast("Add at least one keyword");return}if(!g.deliveryMessage){e.onToast("Add a DM message");return}i=!0,y.disabled=!0,y.replaceChildren(f(s.spinner()),r("span",{text:"Creating\u2026"}));try{await e.onSubmit(g),d()}catch(A){e.onToast(A instanceof Error?A.message:"Something went wrong"),i=!1,y.disabled=!1,y.replaceChildren(f(s.bolt()),r("span",{text:"Create automation"}))}}}),T=r("div",{class:"flxig-dialog",attrs:{role:"dialog","aria-modal":"true"}},r("div",{class:"flxig-dialog__head"},r("div",{},r("div",{class:"flxig-h2",text:"Automate this post"}),r("div",{class:"flxig-muted",text:(h=e.post.caption)!=null&&h.trim()?Te(e.post.caption.trim(),70):"Set up comment & DM replies"})),r("button",{class:"flxig-iconbtn",attrs:{type:"button","aria-label":"Close"},html:s.close(),on:{click:()=>!i&&d()}})),o,r("div",{class:"flxig-dialog__foot"},v({label:"Cancel",variant:"ghost",onClick:()=>!i&&d()}),y));return u(),p(),m(a,[T]),e.mount.appendChild(a),{close:d}}function Te(e,t){return e.length>t?`${e.slice(0,t-1)}\u2026`:e}var Ie='"Inter", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif',Pe="12px",E={light:{background:"#ffffff",foreground:"#0a0a0b",card:"#ffffff",cardForeground:"#0a0a0b",popover:"#ffffff",popoverForeground:"#0a0a0b",primary:"#2563eb",primaryForeground:"#ffffff",secondary:"#f4f4f5",secondaryForeground:"#18181b",muted:"#f4f4f5",mutedForeground:"#71717a",accent:"#eef2ff",accentForeground:"#1e3a8a",destructive:"#ef4444",destructiveForeground:"#ffffff",border:"#e4e4e7",input:"#e4e4e7",ring:"#2563eb"},dark:{background:"#0a0a0b",foreground:"#fafafa",card:"#131316",cardForeground:"#fafafa",popover:"#131316",popoverForeground:"#fafafa",primary:"#3b82f6",primaryForeground:"#ffffff",secondary:"#27272a",secondaryForeground:"#fafafa",muted:"#1b1b1f",mutedForeground:"#a1a1aa",accent:"#1e293b",accentForeground:"#bfdbfe",destructive:"#f87171",destructiveForeground:"#0a0a0b",border:"#27272a",input:"#2a2a2e",ring:"#3b82f6"}};function ae(e={}){var t,n,i,o,a,d,l;return{mode:(t=e.mode)!=null?t:"auto",fontFamily:(n=e.fontFamily)!=null?n:Ie,radius:(i=e.radius)!=null?i:Pe,light:{...E.light,...(a=(o=e.tokens)==null?void 0:o.light)!=null?a:{}},dark:{...E.dark,...(l=(d=e.tokens)==null?void 0:d.dark)!=null?l:{}}}}var Le=e=>e.replace(/[A-Z]/g,t=>`-${t.toLowerCase()}`);function re(e){return Object.keys(e).map(t=>` --flxig-${Le(t)}: ${e[t]};`).join(`
|
|
44
|
+
`)}function le(e){return`:host {
|
|
45
|
+
${re(e.light)}
|
|
46
|
+
--flxig-radius: ${e.radius};
|
|
47
|
+
--flxig-font: ${e.fontFamily};
|
|
48
|
+
}
|
|
49
|
+
:host(.flxig-dark) {
|
|
50
|
+
${re(e.dark)}
|
|
51
|
+
}`}function se(e){return e==="dark"?!0:e==="light"?!1:typeof window!="undefined"&&typeof window.matchMedia=="function"&&window.matchMedia("(prefers-color-scheme: dark)").matches}var de=`
|
|
52
|
+
*, *::before, *::after { box-sizing: border-box; }
|
|
53
|
+
|
|
54
|
+
.flxig-root {
|
|
55
|
+
font-family: var(--flxig-font);
|
|
56
|
+
color: var(--flxig-foreground);
|
|
57
|
+
background: var(--flxig-background);
|
|
58
|
+
border: 1px solid var(--flxig-border);
|
|
59
|
+
border-radius: var(--flxig-radius);
|
|
60
|
+
padding: clamp(20px, 4vw, 36px);
|
|
61
|
+
line-height: 1.5;
|
|
62
|
+
-webkit-font-smoothing: antialiased;
|
|
63
|
+
text-rendering: optimizeLegibility;
|
|
64
|
+
container-type: inline-size;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/* ---- typography ---- */
|
|
68
|
+
.flxig-h1 { font-size: 1.35rem; font-weight: 700; letter-spacing: -0.015em; margin: 0; }
|
|
69
|
+
.flxig-h2 { font-size: 1.05rem; font-weight: 650; letter-spacing: -0.01em; margin: 0; }
|
|
70
|
+
.flxig-muted { color: var(--flxig-muted-foreground); font-size: 0.9rem; margin: 0; }
|
|
71
|
+
.flxig-label { display: block; font-size: 0.8rem; font-weight: 600; margin-bottom: 6px; }
|
|
72
|
+
.flxig-hint { font-size: 0.75rem; color: var(--flxig-muted-foreground); margin-top: 4px; }
|
|
73
|
+
|
|
74
|
+
/* ---- buttons ---- */
|
|
75
|
+
.flxig-btn {
|
|
76
|
+
appearance: none; border: 1px solid transparent; cursor: pointer;
|
|
77
|
+
font-family: inherit; font-size: 0.9rem; font-weight: 600;
|
|
78
|
+
border-radius: calc(var(--flxig-radius) - 4px);
|
|
79
|
+
padding: 10px 16px; display: inline-flex; align-items: center; justify-content: center;
|
|
80
|
+
gap: 8px; transition: filter .15s ease, background .15s ease, border-color .15s ease, opacity .15s ease;
|
|
81
|
+
text-decoration: none; white-space: nowrap;
|
|
82
|
+
}
|
|
83
|
+
.flxig-btn:disabled { opacity: .55; cursor: not-allowed; }
|
|
84
|
+
.flxig-btn--primary { background: var(--flxig-primary); color: var(--flxig-primary-foreground); }
|
|
85
|
+
.flxig-btn--primary:hover:not(:disabled) { filter: brightness(1.07); }
|
|
86
|
+
.flxig-btn--secondary { background: var(--flxig-secondary); color: var(--flxig-secondary-foreground); border-color: var(--flxig-border); }
|
|
87
|
+
.flxig-btn--secondary:hover:not(:disabled) { background: var(--flxig-muted); }
|
|
88
|
+
.flxig-btn--ghost { background: transparent; color: var(--flxig-foreground); }
|
|
89
|
+
.flxig-btn--ghost:hover:not(:disabled) { background: var(--flxig-muted); }
|
|
90
|
+
.flxig-btn--block { width: 100%; }
|
|
91
|
+
.flxig-btn--lg { padding: 13px 20px; font-size: 0.98rem; }
|
|
92
|
+
|
|
93
|
+
/* ---- brand logo: delta chip (light) / bare delta (dark) + wordmark ---- */
|
|
94
|
+
.flxig-brand { display: inline-flex; align-items: center; gap: 7px; color: var(--flxig-foreground); }
|
|
95
|
+
.flxig-brand__chip { display: inline-flex; align-items: center; justify-content: center; background: var(--flxig-primary); border-radius: 6px; padding: 3px; }
|
|
96
|
+
.flxig-brand__img { display: block; width: var(--flxig-logo-size, 18px); height: var(--flxig-logo-size, 18px); object-fit: contain; }
|
|
97
|
+
.flxig-brand__wordmark { display: block; height: var(--flxig-logo-size, 18px); width: auto; }
|
|
98
|
+
:host(.flxig-dark) .flxig-brand__chip { background: transparent; padding: 0; }
|
|
99
|
+
|
|
100
|
+
/* ---- co-brand lockup: "<partner logo> \xD7 flonix" ---- */
|
|
101
|
+
.flxig-cobrand { display: inline-flex; align-items: center; gap: 9px; font-size: 0.9rem; }
|
|
102
|
+
.flxig-cobrand__x { color: var(--flxig-muted-foreground); font-weight: 400; }
|
|
103
|
+
.flxig-partner { display: inline-flex; align-items: center; }
|
|
104
|
+
.flxig-partner__img { display: block; height: 18px; width: auto; max-width: 120px; object-fit: contain; }
|
|
105
|
+
.flxig-partner[data-has-dark="true"] .flxig-partner__img--dark { display: none; }
|
|
106
|
+
:host(.flxig-dark) .flxig-partner[data-has-dark="true"] .flxig-partner__img--light { display: none; }
|
|
107
|
+
:host(.flxig-dark) .flxig-partner[data-has-dark="true"] .flxig-partner__img--dark { display: block; }
|
|
108
|
+
|
|
109
|
+
/* ---- connect screen ---- */
|
|
110
|
+
.flxig-connect { display: flex; flex-direction: column; align-items: center; text-align: center; gap: 18px; padding: clamp(20px, 6cqw, 52px) 8px; }
|
|
111
|
+
.flxig-connect__copy { display: flex; flex-direction: column; gap: 8px; max-width: 420px; }
|
|
112
|
+
.flxig-connect__cta { width: 100%; max-width: 340px; margin-top: 4px; }
|
|
113
|
+
.flxig-connect__foot { margin-top: 6px; }
|
|
114
|
+
|
|
115
|
+
/* ---- posts header ---- */
|
|
116
|
+
.flxig-header { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 18px; flex-wrap: wrap; }
|
|
117
|
+
.flxig-header__id { display: flex; align-items: center; gap: 10px; min-width: 0; }
|
|
118
|
+
.flxig-avatar { width: 38px; height: 38px; border-radius: 999px; display: inline-flex; align-items: center; justify-content: center; background: var(--flxig-accent); color: var(--flxig-accent-foreground); flex: none; }
|
|
119
|
+
.flxig-badge { display: inline-flex; align-items: center; gap: 5px; font-size: 0.72rem; font-weight: 600; padding: 3px 9px; border-radius: 999px; background: var(--flxig-accent); color: var(--flxig-accent-foreground); }
|
|
120
|
+
|
|
121
|
+
/* ---- posts grid ---- */
|
|
122
|
+
.flxig-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 14px; }
|
|
123
|
+
@container (min-width: 520px) { .flxig-grid { grid-template-columns: repeat(3, 1fr); } }
|
|
124
|
+
@container (min-width: 760px) { .flxig-grid { grid-template-columns: repeat(4, 1fr); } }
|
|
125
|
+
|
|
126
|
+
.flxig-tile { border: 1px solid var(--flxig-border); border-radius: var(--flxig-radius); overflow: hidden; background: var(--flxig-card); display: flex; flex-direction: column; }
|
|
127
|
+
.flxig-tile__media { position: relative; aspect-ratio: 1 / 1; background: var(--flxig-muted); overflow: hidden; }
|
|
128
|
+
.flxig-tile__media img { width: 100%; height: 100%; object-fit: cover; display: block; }
|
|
129
|
+
.flxig-tile__ph { width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; color: var(--flxig-muted-foreground); }
|
|
130
|
+
.flxig-tile__type { position: absolute; top: 8px; right: 8px; display: inline-flex; align-items: center; gap: 4px; font-size: 0.68rem; font-weight: 600; padding: 3px 7px; border-radius: 999px; background: color-mix(in srgb, #000 55%, transparent); color: #fff; backdrop-filter: blur(4px); }
|
|
131
|
+
.flxig-tile__body { padding: 10px; display: flex; flex-direction: column; gap: 8px; flex: 1; }
|
|
132
|
+
.flxig-tile__cap { font-size: 0.78rem; color: var(--flxig-muted-foreground); margin: 0; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; min-height: 2.1em; }
|
|
133
|
+
|
|
134
|
+
.flxig-sentinel { height: 1px; }
|
|
135
|
+
.flxig-loadmore { display: flex; justify-content: center; padding: 18px 0 2px; color: var(--flxig-muted-foreground); }
|
|
136
|
+
|
|
137
|
+
/* ---- empty / error / loading ---- */
|
|
138
|
+
.flxig-state { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 12px; text-align: center; padding: 48px 16px; color: var(--flxig-muted-foreground); }
|
|
139
|
+
|
|
140
|
+
/* ---- dialog ---- */
|
|
141
|
+
.flxig-overlay { position: fixed; inset: 0; background: color-mix(in srgb, #000 55%, transparent); display: flex; align-items: center; justify-content: center; padding: 16px; z-index: 2147483000; animation: flxig-fade .15s ease; }
|
|
142
|
+
.flxig-dialog { background: var(--flxig-popover); color: var(--flxig-popover-foreground); border: 1px solid var(--flxig-border); border-radius: var(--flxig-radius); width: min(560px, 100%); max-height: min(88vh, 760px); display: flex; flex-direction: column; overflow: hidden; box-shadow: 0 24px 60px -20px rgba(0,0,0,.5); animation: flxig-pop .18s cubic-bezier(.2,.8,.2,1); }
|
|
143
|
+
.flxig-dialog__head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; padding: 18px 20px; border-bottom: 1px solid var(--flxig-border); }
|
|
144
|
+
.flxig-dialog__body { padding: 18px 20px; overflow-y: auto; display: flex; flex-direction: column; gap: 16px; }
|
|
145
|
+
.flxig-dialog__foot { padding: 14px 20px; border-top: 1px solid var(--flxig-border); display: flex; gap: 10px; justify-content: flex-end; }
|
|
146
|
+
.flxig-iconbtn { appearance: none; background: transparent; border: none; color: var(--flxig-muted-foreground); cursor: pointer; padding: 4px; border-radius: 8px; display: inline-flex; }
|
|
147
|
+
.flxig-iconbtn:hover { background: var(--flxig-muted); color: var(--flxig-foreground); }
|
|
148
|
+
|
|
149
|
+
/* ---- type picker (segmented) ---- */
|
|
150
|
+
.flxig-seg { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
|
|
151
|
+
.flxig-seg__opt { border: 1px solid var(--flxig-border); border-radius: calc(var(--flxig-radius) - 2px); padding: 12px; cursor: pointer; display: flex; gap: 10px; align-items: flex-start; background: var(--flxig-card); transition: border-color .15s, background .15s; }
|
|
152
|
+
.flxig-seg__opt:hover { border-color: var(--flxig-ring); }
|
|
153
|
+
.flxig-seg__opt[data-active="true"] { border-color: var(--flxig-primary); background: var(--flxig-accent); }
|
|
154
|
+
.flxig-seg__ic { color: var(--flxig-primary); margin-top: 2px; }
|
|
155
|
+
.flxig-seg__t { font-weight: 650; font-size: 0.88rem; }
|
|
156
|
+
.flxig-seg__d { font-size: 0.74rem; color: var(--flxig-muted-foreground); margin-top: 2px; }
|
|
157
|
+
|
|
158
|
+
/* ---- form fields ---- */
|
|
159
|
+
.flxig-field { display: block; }
|
|
160
|
+
.flxig-input, .flxig-textarea {
|
|
161
|
+
width: 100%; font-family: inherit; font-size: 0.88rem; color: var(--flxig-foreground);
|
|
162
|
+
background: var(--flxig-background); border: 1px solid var(--flxig-input);
|
|
163
|
+
border-radius: calc(var(--flxig-radius) - 4px); padding: 9px 11px; transition: border-color .15s, box-shadow .15s;
|
|
164
|
+
}
|
|
165
|
+
.flxig-input:focus, .flxig-textarea:focus { outline: none; border-color: var(--flxig-ring); box-shadow: 0 0 0 3px color-mix(in srgb, var(--flxig-ring) 25%, transparent); }
|
|
166
|
+
.flxig-textarea { resize: vertical; min-height: 72px; }
|
|
167
|
+
|
|
168
|
+
/* ---- follow-gate card + switch ---- */
|
|
169
|
+
.flxig-gate { border: 1px solid var(--flxig-border); border-radius: calc(var(--flxig-radius) - 2px); padding: 14px; display: flex; flex-direction: column; gap: 12px; background: var(--flxig-card); }
|
|
170
|
+
.flxig-gate__top { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
|
|
171
|
+
.flxig-gate__fields { display: flex; flex-direction: column; gap: 12px; }
|
|
172
|
+
.flxig-gate__fields[data-off="true"] { opacity: .5; pointer-events: none; }
|
|
173
|
+
|
|
174
|
+
.flxig-switch { position: relative; width: 40px; height: 23px; flex: none; }
|
|
175
|
+
.flxig-switch input { position: absolute; opacity: 0; width: 100%; height: 100%; margin: 0; cursor: pointer; }
|
|
176
|
+
.flxig-switch__track { position: absolute; inset: 0; background: var(--flxig-input); border-radius: 999px; transition: background .15s; }
|
|
177
|
+
.flxig-switch__thumb { position: absolute; top: 2px; left: 2px; width: 19px; height: 19px; border-radius: 999px; background: #fff; transition: transform .15s; box-shadow: 0 1px 3px rgba(0,0,0,.3); }
|
|
178
|
+
.flxig-switch input:checked ~ .flxig-switch__track { background: var(--flxig-primary); }
|
|
179
|
+
.flxig-switch input:checked ~ .flxig-switch__thumb { transform: translateX(17px); }
|
|
180
|
+
|
|
181
|
+
/* ---- chips (keywords) ---- */
|
|
182
|
+
.flxig-chips { display: flex; flex-wrap: wrap; gap: 6px; padding: 6px; border: 1px solid var(--flxig-input); border-radius: calc(var(--flxig-radius) - 4px); background: var(--flxig-background); }
|
|
183
|
+
.flxig-chip { display: inline-flex; align-items: center; gap: 6px; background: var(--flxig-secondary); color: var(--flxig-secondary-foreground); font-size: 0.78rem; font-weight: 600; padding: 4px 8px; border-radius: 999px; }
|
|
184
|
+
.flxig-chip button { appearance: none; border: none; background: transparent; color: inherit; cursor: pointer; opacity: .6; padding: 0; display: inline-flex; }
|
|
185
|
+
.flxig-chip button:hover { opacity: 1; }
|
|
186
|
+
.flxig-chips input { flex: 1; min-width: 80px; border: none; outline: none; background: transparent; color: var(--flxig-foreground); font-family: inherit; font-size: 0.82rem; padding: 4px; }
|
|
187
|
+
|
|
188
|
+
/* ---- link buttons editor ---- */
|
|
189
|
+
.flxig-links__wrap { display: flex; flex-direction: column; gap: 10px; }
|
|
190
|
+
.flxig-links { display: flex; flex-direction: column; gap: 10px; }
|
|
191
|
+
.flxig-link { display: flex; align-items: center; gap: 8px; }
|
|
192
|
+
.flxig-link__ic { color: var(--flxig-muted-foreground); flex: none; display: inline-flex; }
|
|
193
|
+
.flxig-link__inputs { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.5fr); gap: 8px; flex: 1; min-width: 0; }
|
|
194
|
+
.flxig-links__add { align-self: flex-start; padding-left: 8px; padding-right: 12px; }
|
|
195
|
+
@container (max-width: 440px) { .flxig-link__inputs { grid-template-columns: 1fr; } }
|
|
196
|
+
|
|
197
|
+
/* ---- toast ---- */
|
|
198
|
+
.flxig-toast { position: fixed; bottom: 20px; left: 50%; transform: translateX(-50%); background: var(--flxig-foreground); color: var(--flxig-background); font-size: 0.85rem; font-weight: 600; padding: 10px 16px; border-radius: 999px; display: inline-flex; align-items: center; gap: 8px; z-index: 2147483001; box-shadow: 0 10px 30px -10px rgba(0,0,0,.5); animation: flxig-pop .2s ease; }
|
|
199
|
+
|
|
200
|
+
/* ---- footer attribution ---- */
|
|
201
|
+
.flxig-attrib { margin-top: 18px; padding-top: 14px; border-top: 1px solid var(--flxig-border); display: flex; align-items: center; justify-content: center; gap: 6px; font-size: 0.72rem; color: var(--flxig-muted-foreground); }
|
|
202
|
+
|
|
203
|
+
/* ---- animations ---- */
|
|
204
|
+
.flxig-spin { animation: flxig-rotate .8s linear infinite; }
|
|
205
|
+
@keyframes flxig-rotate { to { transform: rotate(360deg); } }
|
|
206
|
+
@keyframes flxig-fade { from { opacity: 0; } to { opacity: 1; } }
|
|
207
|
+
@keyframes flxig-pop { from { opacity: 0; transform: scale(.97); } to { opacity: 1; transform: scale(1); } }
|
|
208
|
+
@media (prefers-reduced-motion: reduce) { *, *::before, *::after { animation-duration: .001ms !important; transition-duration: .001ms !important; } }
|
|
209
|
+
`;var ce="flxig_connected",Be="https://flonix.pro",P=class{constructor(t,n){this.mediaQuery=null;this.token=null;this.account=null;this.postsView=null;this.cursor=null;this.connecting=!1;this.destroyed=!1;this.onSchemeChange=t=>this.applyMode(t.matches);var o,a;this.config=n,this.transport=(a=n.transport)!=null?a:k((o=n.baseUrl)!=null?o:Be),this.host=document.createElement("div"),this.host.setAttribute("data-flonix-ig",""),t.appendChild(this.host),this.shadow=this.host.attachShadow({mode:"open"});let i=ae(n.theme);this.shadow.appendChild(r("style",{text:`${le(i)}
|
|
210
|
+
${de}`})),this.root=r("div",{class:"flxig-root"}),this.content=r("div",{class:"flxig-content"}),this.root.appendChild(this.content),this.shadow.appendChild(this.root),this.applyMode(se(i.mode)),i.mode==="auto"&&typeof window.matchMedia=="function"&&(this.mediaQuery=window.matchMedia("(prefers-color-scheme: dark)"),this.mediaQuery.addEventListener("change",this.onSchemeChange)),this.init()}applyMode(t){this.host.classList.toggle("flxig-dark",t)}refresh(){this.cursor=null,this.init()}unmount(){var t,n;this.destroyed=!0,(t=this.postsView)==null||t.destroy(),(n=this.mediaQuery)==null||n.removeEventListener("change",this.onSchemeChange),this.host.remove()}fail(t){var i,o;let n=t instanceof Error?t:new Error(String(t));return(o=(i=this.config).onError)==null||o.call(i,n),n}async init(){var t,n,i;this.renderLoading();try{let o=await this.transport.session({apiKey:this.config.apiKey,user:this.config.user});if(this.destroyed)return;this.token=o.token,this.account=o.account,o.connected?(this.clearReturnFlag(),(i=(n=this.config).onConnected)==null||i.call(n,(t=o.account)!=null?t:{instagramId:null,username:null}),await this.renderPosts()):this.renderConnect()}catch(o){this.renderError(this.fail(o).message)}}async startConnect(){if(!(!this.token||this.connecting)){this.connecting=!0,this.renderConnect();try{let{authorizeUrl:t}=await this.transport.connectStart({token:this.token,returnUrl:this.resolveReturnUrl()});window.location.href=t}catch(t){this.connecting=!1,this.renderConnect(),this.toast(this.fail(t).message)}}}async renderPosts(){let t=ie({account:this.account,onAutomate:n=>this.openDialog(n),onLoadMore:()=>{this.loadMore()}});this.postsView=t,this.swap(t.element),await this.loadMore(!0)}async loadMore(t=!1){let n=this.postsView;if(!(!n||!this.token)){n.setLoadingMore(!0);try{let{posts:i,nextCursor:o}=await this.transport.posts({token:this.token,cursor:this.cursor});if(this.destroyed)return;if(t&&i.length===0){n.showEmpty();return}n.appendPosts(i),this.cursor=o,n.setHasMore(!!o)}catch(i){this.toast(this.fail(i).message)}finally{n.setLoadingMore(!1)}}}openDialog(t){this.token&&oe({mount:this.shadow,post:t,account:this.account,onToast:n=>this.toast(n),onSubmit:n=>this.createAutomation(n)})}async createAutomation(t){var i,o;if(!this.token)throw new Error("Not connected");let n=await this.transport.createAutomation({token:this.token,data:t});(o=(i=this.config).onAutomationCreated)==null||o.call(i,n),this.toast("Automation created \u2713")}swap(t){M(this.content),this.content.appendChild(t)}renderConnect(){this.swap(te({connecting:this.connecting,partner:this.config.partner,onConnect:()=>{this.startConnect()}}))}renderLoading(){this.swap(C({icon:s.spinner(26),title:"Loading\u2026"}))}renderError(t){this.swap(C({icon:s.close(26),title:"Couldn't load",detail:t}))}toast(t){let n=f(`<div class="flxig-toast">${s.bolt(14)}<span></span></div>`);n.querySelector("span").textContent=t,this.shadow.appendChild(n),setTimeout(()=>n.remove(),2600)}resolveReturnUrl(){return this.config.returnUrl?this.config.returnUrl:typeof window=="undefined"?"":window.location.href}clearReturnFlag(){var n;if(typeof window=="undefined"||!((n=window.history)!=null&&n.replaceState))return;let t=new URL(window.location.href);t.searchParams.has(ce)&&(t.searchParams.delete(ce),window.history.replaceState({},"",t.toString()))}};var L=e=>new Promise(t=>setTimeout(t,e)),ge=["IMAGE","CAROUSEL","REELS","VIDEO","IMAGE"],pe=["New drop is live \u{1F525} comment LINK for the shop","Behind the scenes of today's shoot","Our bestseller is back in stock \u2728","How to style this 3 ways \u{1F447}","Limited edition \u2014 only 50 made","Weekend sale starts now \u{1F6CD}\uFE0F",null,"Tag a friend who needs this \u{1F499}"];function Se(e,t){return Array.from({length:t},(n,i)=>{var a,d;let o=e*t+i;return{id:`mock_${o}`,caption:(a=pe[o%pe.length])!=null?a:null,media:`https://picsum.photos/seed/flonix${o}/600/600`,mediaType:(d=ge[o%ge.length])!=null?d:"IMAGE",permalink:null,timestamp:new Date(Date.now()-o*864e5).toISOString()}})}function K(e={}){var a,d,l;let t=(a=e.totalPages)!=null?a:3,n=(d=e.perPage)!=null?d:8,i=`flxig.mock.connected.${(l=e.namespace)!=null?l:"default"}`,o=()=>{try{return localStorage.getItem(i)==="1"}catch{return!1}};return{async session(){await L(400);let c=o();return{connected:c,token:"mock-session-token",account:c?{instagramId:"17890000000",username:"your_brand"}:null}},async connectStart({returnUrl:c}){await L(500);try{localStorage.setItem(i,"1")}catch{}let u=new URL(c,window.location.href);return u.searchParams.set("flxig_connected","1"),{authorizeUrl:u.toString()}},async posts({cursor:c}){await L(500);let u=c?Number(c):0,x=Se(u,n),p=u+1;return{posts:x,nextCursor:p<t?String(p):null}},async createAutomation(){return await L(700),{id:`mock_automation_${Date.now()}`}}}}var z="0.1.0";function R(e,t){var i,o,a;let n=typeof e=="string"?document.querySelector(e):e;if(!n)throw new Error(`FlonixIG.mount: target not found: ${String(e)}`);if(!(t!=null&&t.apiKey))throw new Error("FlonixIG.mount: config.apiKey is required");if(!((i=t==null?void 0:t.user)!=null&&i.id))throw new Error("FlonixIG.mount: config.user.id is required");if(!((o=t==null?void 0:t.partner)!=null&&o.logo)||!((a=t==null?void 0:t.partner)!=null&&a.name))throw new Error("FlonixIG.mount: config.partner.name and config.partner.logo are required");return new P(n,t)}var fe={mount:R,version:z};return we(Ne);})();
|
|
211
|
+
//# sourceMappingURL=flonix-ig.global.js.map
|