@plaidev/karte-action-sdk 1.1.267 → 1.1.268-29083022.42c3d847

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.
@@ -4,7 +4,7 @@ import { onMount as onMount$1, onDestroy as onDestroy$1, beforeUpdate as beforeU
4
4
  import 'svelte/internal/disclose-version';
5
5
  import 'svelte/internal/flags/legacy';
6
6
  import * as $ from 'svelte/internal/client';
7
- import 'svelte/easing';
7
+ import { linear, elasticOut, cubicOut } from 'svelte/easing';
8
8
 
9
9
  /** @internal */
10
10
  const ACTION_HOOK_LABEL = '__ACTION_HOOK__';
@@ -38,9 +38,15 @@ const KARTE_MODAL_ROOT = 'karte-modal-root';
38
38
  /** @internal */
39
39
  const NOOP = (_args) => { }; // eslint-disable-line @typescript-eslint/no-unused-vars
40
40
  /** @internal */
41
- const isPreview = () => {
42
- return true;
43
- };
41
+ const isPreview = () => (isInFrame() );
42
+ const isCanvasPreview = () => typeof document !== 'undefined'
43
+ ? (document?.querySelector('#preview')?.getAttribute('data-canvas-preview') ?? 'false') ===
44
+ 'true'
45
+ : false;
46
+ const isOnSite = () => typeof document !== 'undefined'
47
+ ? (document?.querySelector('#preview')?.getAttribute('data-on-site') ?? 'true') === 'true'
48
+ : true;
49
+ const isInFrame = () => window && window.self !== window.top;
44
50
  /** @internal */
45
51
  const setPreviousFocus = () => {
46
52
  const previously_focused = typeof document !== 'undefined' && document.activeElement;
@@ -223,6 +229,10 @@ function onTime(time, fn) {
223
229
  const timeoutHandler = setTimeout(fn, time);
224
230
  return () => timeoutHandler && clearTimeout(timeoutHandler);
225
231
  }
232
+ /** @internal */
233
+ function randStr(digit = 8) {
234
+ return Math.random().toString(32).substring(digit);
235
+ }
226
236
  /**
227
237
  * Goolge Fonts用のURLを生成
228
238
  *
@@ -754,7 +764,7 @@ const state = writable('/');
754
764
  * @public
755
765
  */
756
766
  function setState$1(stateId, options) {
757
- if (options?.disableInPreview)
767
+ if (isPreview() && options?.disableInPreview)
758
768
  return;
759
769
  state.set(stateId);
760
770
  }
@@ -1198,8 +1208,11 @@ function cloneToJson(data) {
1198
1208
 
1199
1209
  // prettier-ignore
1200
1210
  /** @internal */
1201
- const actionId = ALL_ACTION_ID
1202
- ;
1211
+ const actionId = isPreview()
1212
+ ? ALL_ACTION_ID
1213
+ : typeof __FLYER_GEN_ACTION_ID_ON_BUILD__ === 'string'
1214
+ ? __FLYER_GEN_ACTION_ID_ON_BUILD__
1215
+ : randStr();
1203
1216
  /** @internal */
1204
1217
  const ACTION_DESTROY_EVENT = `KARTE-ACTION-DESTROY-${actionId}`;
1205
1218
  /** @internal */
@@ -1339,6 +1352,58 @@ function showOnTime(props, show = NOOP) {
1339
1352
  ? onTime(props.show_on_time_count * 1000, () => show())
1340
1353
  : null;
1341
1354
  }
1355
+ /** @internal */
1356
+ function and(fn, ...conditionFns) {
1357
+ return checkAndDo((conditions, idx) => {
1358
+ conditions[idx] = true;
1359
+ return conditions.every(t => t == null || t);
1360
+ }, fn, ...conditionFns);
1361
+ }
1362
+ /** @internal */
1363
+ function or(fn, ...conditionFns) {
1364
+ return checkAndDo((conditions, idx) => {
1365
+ if (conditions.some(t => t)) {
1366
+ return conditions[idx]; // this is true when show_on_scroll_reenter is true
1367
+ }
1368
+ conditions[idx] = true;
1369
+ return true;
1370
+ }, fn, ...conditionFns);
1371
+ }
1372
+ function checkAndDo(checkFn, fn, ...conditionFns) {
1373
+ let initialized = false;
1374
+ const checkBeforeInitialized = [];
1375
+ let haveCondition = true;
1376
+ const conditions = Array(conditionFns.length).fill(null);
1377
+ const checkAndDos = Array(conditionFns.length).fill(() => { });
1378
+ const cleanups = Array(conditionFns.length).fill(null);
1379
+ const generageCheckAndDo = (idx) => () => {
1380
+ if (!initialized) {
1381
+ checkBeforeInitialized.push(idx);
1382
+ return;
1383
+ }
1384
+ if (!haveCondition || !checkFn(conditions, idx))
1385
+ return;
1386
+ fn?.();
1387
+ };
1388
+ conditionFns.forEach((conditionFn, i) => {
1389
+ const checkAndDo = generageCheckAndDo(i);
1390
+ checkAndDos[i] = checkAndDo;
1391
+ const cleanup = conditionFn(checkAndDo);
1392
+ cleanups[i] = cleanup;
1393
+ if (cleanup != null)
1394
+ conditions[i] = false;
1395
+ });
1396
+ haveCondition = conditions.some(c => c !== null);
1397
+ const cleanupAll = () => {
1398
+ cleanups.forEach((cleanup, i) => {
1399
+ cleanup?.();
1400
+ cleanups[i] = null;
1401
+ });
1402
+ };
1403
+ initialized = true;
1404
+ checkBeforeInitialized.forEach(i => checkAndDos[i]());
1405
+ return haveCondition ? cleanupAll : null;
1406
+ }
1342
1407
 
1343
1408
  /**
1344
1409
  * アクションテーブルに関連するコードの管理
@@ -1553,8 +1618,23 @@ const loadActionTableQuery = async (config, data, api_key, collection_endpoint)
1553
1618
  /** @internal */
1554
1619
  const loadActionTable = async (config, data, api_key, collection_endpoint) => {
1555
1620
  console.debug('[debug] loadActionTable', isPreview(), api_key, collection_endpoint, JSON.stringify(config));
1556
- const results = config.map(c => c.preview_value)
1557
- ;
1621
+ const results = isPreview()
1622
+ ? config.map(c => c.preview_value)
1623
+ : await Promise.all(config
1624
+ .filter(c => c.resolver === 'action-table-row' ||
1625
+ c.resolver === 'action-table-rows' ||
1626
+ c.resolver === 'action-table-query')
1627
+ .map(async (c) => {
1628
+ if (c.resolver === 'action-table-row') {
1629
+ return await loadActionTableRow(c, data, api_key, collection_endpoint);
1630
+ }
1631
+ else if (c.resolver === 'action-table-rows') {
1632
+ return await loadActionTableRows(c, data, api_key, collection_endpoint);
1633
+ }
1634
+ else if (c.resolver === 'action-table-query') {
1635
+ return await loadActionTableQuery(c, data, api_key, collection_endpoint);
1636
+ }
1637
+ }));
1558
1638
  return config.reduce((acc, c, i) => {
1559
1639
  const value = results[i] ?? c.query.default_value;
1560
1640
  if (value) {
@@ -1587,6 +1667,32 @@ function initActionTable(localVariablesQuery) {
1587
1667
  setVariables(initValues);
1588
1668
  }
1589
1669
 
1670
+ /**
1671
+ * モーダル(ポップアップ)に関連するコードの管理
1672
+ *
1673
+ * アクションのShow, Close, ChangeStateの状態はここで管理する。
1674
+ */
1675
+ /**
1676
+ * アクションを表示する
1677
+ *
1678
+ * @public
1679
+ */
1680
+ function showAction$1() {
1681
+ const event = new CustomEvent(ACTION_SHOW_EVENT, { detail: { trigger: 'custom' } });
1682
+ window.dispatchEvent(event);
1683
+ }
1684
+ /**
1685
+ * アクションを閉じる
1686
+ *
1687
+ * @param trigger - 閉じた時のトリガー。デフォルト `'none'`
1688
+ *
1689
+ * @public
1690
+ */
1691
+ function closeAction$1(trigger = 'none') {
1692
+ const event = new CustomEvent(ACTION_CLOSE_EVENT, { detail: { trigger } });
1693
+ window.dispatchEvent(event);
1694
+ }
1695
+
1590
1696
  /**
1591
1697
  * モーダル(ポップアップ)に関連するコードの管理
1592
1698
  *
@@ -1604,12 +1710,57 @@ const handleState = (event) => {
1604
1710
  });
1605
1711
  }
1606
1712
  };
1713
+ /**
1714
+ * アクションが表示 (show) された後にフックする関数
1715
+ *
1716
+ * @param fn - 呼び出されるフック関数
1717
+ *
1718
+ * @public
1719
+ */
1720
+ function onShow(fn) {
1721
+ let { onShowHandlers } = getInternalHandlers();
1722
+ if (!onShowHandlers) {
1723
+ onShowHandlers = [];
1724
+ }
1725
+ onShowHandlers.push(fn);
1726
+ setInternalHandlers({ onShowHandlers });
1727
+ }
1728
+ /**
1729
+ * アクションがクローズ (close) される前にフックする関数
1730
+ *
1731
+ * @param fn - 呼び出されるフック関数
1732
+ *
1733
+ * @public
1734
+ */
1735
+ function onClose(fn) {
1736
+ let { onCloseHandlers } = getInternalHandlers();
1737
+ if (!onCloseHandlers) {
1738
+ onCloseHandlers = [];
1739
+ }
1740
+ onCloseHandlers.push(fn);
1741
+ setInternalHandlers({ onCloseHandlers });
1742
+ }
1743
+ /**
1744
+ * アクションのステートが変更された (changeState) 後にフックする関数
1745
+ *
1746
+ * @param fn - 呼び出されるフック関数
1747
+ *
1748
+ * @public
1749
+ */
1750
+ function onChangeState(fn) {
1751
+ let { onChangeStateHandlers } = getInternalHandlers();
1752
+ if (!onChangeStateHandlers) {
1753
+ onChangeStateHandlers = [];
1754
+ }
1755
+ onChangeStateHandlers.push(fn);
1756
+ setInternalHandlers({ onChangeStateHandlers });
1757
+ }
1607
1758
  /**
1608
1759
  * アクションを表示する
1609
1760
  *
1610
1761
  * @public
1611
1762
  */
1612
- function showAction$1() {
1763
+ function showAction() {
1613
1764
  const event = new CustomEvent(ACTION_SHOW_EVENT, { detail: { trigger: 'custom' } });
1614
1765
  window.dispatchEvent(event);
1615
1766
  }
@@ -1620,10 +1771,114 @@ function showAction$1() {
1620
1771
  *
1621
1772
  * @public
1622
1773
  */
1623
- function closeAction$1(trigger = 'none') {
1774
+ function closeAction(trigger = 'none') {
1624
1775
  const event = new CustomEvent(ACTION_CLOSE_EVENT, { detail: { trigger } });
1625
1776
  window.dispatchEvent(event);
1626
1777
  }
1778
+ /**
1779
+ * アクションに CSS を適用する
1780
+ *
1781
+ * @param css - 適用する CSS
1782
+ *
1783
+ * @returns 適用された style 要素を返す Promise
1784
+ *
1785
+ * @public
1786
+ */
1787
+ async function applyCss(css) {
1788
+ return new Promise((resolve, reject) => {
1789
+ const style = document.createElement('style');
1790
+ style.textContent = css;
1791
+ const shadowRoot = getActionRoot();
1792
+ if (!shadowRoot)
1793
+ return;
1794
+ shadowRoot.append(style);
1795
+ style.addEventListener('load', () => resolve(style));
1796
+ style.addEventListener('error', () => reject(style));
1797
+ });
1798
+ }
1799
+ async function fixFontFaceIssue(href, cssRules) {
1800
+ const css = new CSSStyleSheet();
1801
+ // @ts-ignore
1802
+ await css.replace(cssRules);
1803
+ const rules = [];
1804
+ const fixedRules = [];
1805
+ Array.from(css.cssRules).forEach(cssRule => {
1806
+ if (cssRule.type !== 5) {
1807
+ rules.push(cssRule.cssText);
1808
+ }
1809
+ // type 5 is @font-face
1810
+ const split = href.split('/');
1811
+ const stylePath = split.slice(0, split.length - 1).join('/');
1812
+ const cssText = cssRule.cssText;
1813
+ const newCssText = cssText.replace(
1814
+ // relative paths
1815
+ /url\s*\(\s*['"]?(?!((\/)|((?:https?:)?\/\/)|(?:data:?:)))([^'")]+)['"]?\s*\)/g, `url("${stylePath}/$4")`);
1816
+ if (cssText === newCssText)
1817
+ return;
1818
+ fixedRules.push(newCssText);
1819
+ });
1820
+ return [rules.join('\n'), fixedRules.join('\n')];
1821
+ }
1822
+ /**
1823
+ * アクションにグローバルなスタイルを読み込む
1824
+ *
1825
+ * @param href - style ファイルのリンク URL
1826
+ *
1827
+ * @public
1828
+ */
1829
+ async function loadStyle(href) {
1830
+ const sr = getActionRoot();
1831
+ if (!sr)
1832
+ return;
1833
+ let cssRules = '';
1834
+ try {
1835
+ const res = await fetch(href);
1836
+ cssRules = await res.text();
1837
+ }
1838
+ catch (_) {
1839
+ // pass
1840
+ }
1841
+ if (!cssRules)
1842
+ return;
1843
+ // Chromeのバグで、Shadow Rootの@font-faceを絶対パスで指定する必要がある
1844
+ // @see https://stackoverflow.com/a/63717709
1845
+ const [rules, fontFaceRules] = await fixFontFaceIssue(href, cssRules);
1846
+ const css = new CSSStyleSheet();
1847
+ // @ts-ignore
1848
+ await css.replace(rules);
1849
+ const fontFaceCss = new CSSStyleSheet();
1850
+ // @ts-ignore
1851
+ await fontFaceCss.replace(fontFaceRules);
1852
+ // @ts-ignore
1853
+ sr.adoptedStyleSheets = [...sr.adoptedStyleSheets, css, fontFaceCss];
1854
+ // Chromeのバグで、ページとShadow Rootの両方に、@font-faceを設定する必要がある
1855
+ // @see https://stackoverflow.com/a/63717709
1856
+ // @ts-ignore
1857
+ document.adoptedStyleSheets = [...document.adoptedStyleSheets, css, fontFaceCss];
1858
+ }
1859
+ // @internal
1860
+ function getCssVariables(data) {
1861
+ return Object.entries(data)
1862
+ .filter(([key, value]) => {
1863
+ return ['string', 'number'].includes(typeof value) && key.startsWith('--');
1864
+ })
1865
+ .map(([key, value]) => `${key}:${value}`)
1866
+ .join(';');
1867
+ }
1868
+ /**
1869
+ * アクションのルートの DOM 要素を取得する
1870
+ *
1871
+ * @returns アクションがルートの DOM 要素 を持つ場合は DOM 要素を返します。ない場合は `null` を返します
1872
+ *
1873
+ * @public
1874
+ */
1875
+ function getActionRoot() {
1876
+ const root = document.querySelector(`.${KARTE_ACTION_ROOT}[data-${KARTE_ACTION_RID}='${actionId}']`);
1877
+ if (!root?.shadowRoot) {
1878
+ return null;
1879
+ }
1880
+ return root.shadowRoot;
1881
+ }
1627
1882
  /** @internal */
1628
1883
  function createModal(App, options = {
1629
1884
  send: () => { },
@@ -1691,7 +1946,7 @@ function createModal(App, options = {
1691
1946
  if (app) {
1692
1947
  return;
1693
1948
  }
1694
- if (trigger === 'custom') {
1949
+ if (!isOnSite() && trigger === 'custom') {
1695
1950
  return;
1696
1951
  }
1697
1952
  if (trigger === 'custom' && (options.props.show_on_scroll || options.props.show_on_time)) {
@@ -1718,9 +1973,9 @@ function createModal(App, options = {
1718
1973
  if (app) {
1719
1974
  return;
1720
1975
  }
1976
+ const target = ensureActionRoot(isOnSite());
1721
1977
  const props = {
1722
- target: ensureActionRoot$1(!true),
1723
- hydrate: true,
1978
+ target,
1724
1979
  props: {
1725
1980
  send: options.send,
1726
1981
  publish: options.publish,
@@ -1755,17 +2010,43 @@ function createModal(App, options = {
1755
2010
  },
1756
2011
  },
1757
2012
  };
1758
- app = svelte.hydrate(App, props)
1759
-
2013
+ app = // @ts-ignore -- Svelte3 では `mount` は存在しない
2014
+ svelte.mount(App, props)
1760
2015
  ;
1761
2016
  };
1762
2017
  const handleShow = (event) => {
1763
2018
  const trigger = event?.detail?.trigger ? event.detail.trigger : 'none';
1764
2019
  show(trigger);
1765
2020
  };
2021
+ const currying = (conditionFn, options) => (fn) => conditionFn(options.props, fn);
1766
2022
  const autoShow = () => {
1767
2023
  return show('auto');
1768
2024
  };
2025
+ const autoClose = () => {
2026
+ return close('auto');
2027
+ };
2028
+ const listenCloseTrigger = () => {
2029
+ const cleanups = [];
2030
+ const curried = fn => hideOnScroll(options.props, fn, autoShow);
2031
+ if (options.props.hide_and_condition) {
2032
+ cleanups.push(and(autoClose, curried, currying(hideOnTime, options)) || NOOP);
2033
+ }
2034
+ else {
2035
+ cleanups.push(or(autoClose, curried, currying(hideOnTime, options)) || NOOP);
2036
+ }
2037
+ return cleanups;
2038
+ };
2039
+ const listenShowTrigger = () => {
2040
+ const cleanups = [];
2041
+ const curried = fn => showOnScroll(options.props, fn, autoClose);
2042
+ if (options.props.show_and_condition) {
2043
+ cleanups.push(and(autoShow, curried, currying(showOnTime, options)) || NOOP);
2044
+ }
2045
+ else {
2046
+ cleanups.push(or(autoShow, curried, currying(showOnTime, options)) || NOOP);
2047
+ }
2048
+ return cleanups;
2049
+ };
1769
2050
  // ここからメインの処理
1770
2051
  initialize({ send: options.send, initialState: data.initial_state });
1771
2052
  // ActionTable APIへの非同期リクエスト
@@ -1780,9 +2061,13 @@ function createModal(App, options = {
1780
2061
  window.addEventListener(ACTION_CHANGE_STATE_EVENT, handleState);
1781
2062
  let showTriggerCleanups = [];
1782
2063
  let closeTriggerCleanups = [];
1783
- {
2064
+ if (!isOnSite()) {
1784
2065
  autoShow();
1785
2066
  }
2067
+ else {
2068
+ showTriggerCleanups = listenShowTrigger();
2069
+ closeTriggerCleanups = listenCloseTrigger();
2070
+ }
1786
2071
  // 旧Widget API IFの処理
1787
2072
  const { onCreateHandlers } = getInternalHandlers();
1788
2073
  if (onCreateHandlers) {
@@ -1811,7 +2096,7 @@ function createModal(App, options = {
1811
2096
  return appCleanup;
1812
2097
  }
1813
2098
  /** @internal */
1814
- function ensureActionRoot$1(useShadow = true) {
2099
+ function ensureActionRoot(useShadow = true) {
1815
2100
  const systemConfig = getSystem();
1816
2101
  const rootAttrs = {
1817
2102
  class: `${KARTE_ACTION_ROOT} ${KARTE_MODAL_ROOT}`,
@@ -1834,29 +2119,138 @@ function ensureActionRoot$1(useShadow = true) {
1834
2119
  return el;
1835
2120
  }
1836
2121
  }
1837
-
1838
2122
  /**
1839
- * スクリプト接客が利用するコードの管理
2123
+ * 非推奨
2124
+ *
2125
+ * @deprecated 非推奨
2126
+ *
2127
+ * @internal
1840
2128
  */
1841
- /** @internal */
1842
- async function runScript$1(options = {
2129
+ const show = showAction;
2130
+ /**
2131
+ * 非推奨
2132
+ *
2133
+ * @deprecated 非推奨
2134
+ *
2135
+ * @internal
2136
+ */
2137
+ const close = closeAction;
2138
+ /**
2139
+ * 非推奨
2140
+ *
2141
+ * @deprecated 非推奨
2142
+ *
2143
+ * @internal
2144
+ */
2145
+ const ensureModalRoot = ensureActionRoot;
2146
+ /**
2147
+ * 非推奨
2148
+ *
2149
+ * @deprecated 非推奨
2150
+ *
2151
+ * @internal
2152
+ */
2153
+ function createApp(App, options = {
1843
2154
  send: () => { },
1844
2155
  publish: () => { },
1845
2156
  props: {},
1846
2157
  variables: {},
1847
2158
  localVariablesQuery: undefined,
1848
- karteTemplate: {},
1849
- context: { api_key: '', collection_endpoint: undefined },
2159
+ context: { api_key: '' },
1850
2160
  }) {
1851
- if (!options.onCreate)
1852
- return;
1853
- let data = getVariables();
1854
- initialize({ send: options.send, initialState: data.initial_state });
1855
- initActionTable(options.localVariablesQuery);
1856
- const { success } = await setupActionTable(options.localVariablesQuery, data, data.api_key, options.context.collection_endpoint);
1857
- if (!success)
1858
- return;
1859
- // Action Tableの取得結果を反映する
2161
+ let app = null;
2162
+ const close = () => {
2163
+ if (app) {
2164
+ {
2165
+ // @ts-ignore -- Svelte3 では `unmount` は存在しない
2166
+ svelte.unmount(app);
2167
+ }
2168
+ app = null;
2169
+ }
2170
+ };
2171
+ const appArgs = {
2172
+ target: null,
2173
+ props: {
2174
+ send: options.send,
2175
+ publish: options.publish,
2176
+ close,
2177
+ data: {
2178
+ ...options.props,
2179
+ ...options.variables,
2180
+ },
2181
+ },
2182
+ };
2183
+ const win = ensureActionRoot(isOnSite());
2184
+ appArgs.target = win;
2185
+ return {
2186
+ close,
2187
+ show: () => {
2188
+ if (app) {
2189
+ return;
2190
+ }
2191
+ options.send('message_open');
2192
+ app = // @ts-ignore -- Svelte3 では `mount` は存在しない
2193
+ svelte.mount(App, appArgs)
2194
+ ;
2195
+ },
2196
+ };
2197
+ }
2198
+ /**
2199
+ * 非推奨
2200
+ *
2201
+ * @deprecated 非推奨
2202
+ *
2203
+ * @internal
2204
+ */
2205
+ function createFog({ color = '#000', opacity = '50%', zIndex = 999, onclick, }) {
2206
+ console.log('createFog');
2207
+ const root = ensureModalRoot();
2208
+ if (root.querySelector('.__krt-fog')) {
2209
+ return { fog: null, close: () => { } };
2210
+ }
2211
+ const fog = document.createElement('div');
2212
+ fog.className = '__krt-fog';
2213
+ Object.assign(fog.style, {
2214
+ position: 'fixed',
2215
+ left: 0,
2216
+ top: 0,
2217
+ width: '100%',
2218
+ height: '100%',
2219
+ 'z-index': zIndex,
2220
+ 'background-color': color,
2221
+ opacity,
2222
+ });
2223
+ const close = () => {
2224
+ onclick();
2225
+ fog.remove();
2226
+ };
2227
+ fog.onclick = close;
2228
+ root.appendChild(fog);
2229
+ return { fog, close };
2230
+ }
2231
+
2232
+ /**
2233
+ * スクリプト接客が利用するコードの管理
2234
+ */
2235
+ /** @internal */
2236
+ async function runScript$1(options = {
2237
+ send: () => { },
2238
+ publish: () => { },
2239
+ props: {},
2240
+ variables: {},
2241
+ localVariablesQuery: undefined,
2242
+ karteTemplate: {},
2243
+ context: { api_key: '', collection_endpoint: undefined },
2244
+ }) {
2245
+ if (!options.onCreate)
2246
+ return;
2247
+ let data = getVariables();
2248
+ initialize({ send: options.send, initialState: data.initial_state });
2249
+ initActionTable(options.localVariablesQuery);
2250
+ const { success } = await setupActionTable(options.localVariablesQuery, data, data.api_key, options.context.collection_endpoint);
2251
+ if (!success)
2252
+ return;
2253
+ // Action Tableの取得結果を反映する
1860
2254
  data = getVariables();
1861
2255
  const actionProps = {
1862
2256
  send: options.send,
@@ -2002,7 +2396,7 @@ function create(App, options) {
2002
2396
  runScript$1(options);
2003
2397
  }
2004
2398
  else {
2005
- modalCleanup = createModal(App, options);
2399
+ modalCleanup = createModal(App, options) ;
2006
2400
  }
2007
2401
  return () => {
2008
2402
  loggerCleanup();
@@ -2070,313 +2464,6 @@ function destroy() {
2070
2464
  dispatchDestroyEvent();
2071
2465
  }
2072
2466
 
2073
- /**
2074
- * モーダル(ポップアップ)に関連するコードの管理
2075
- *
2076
- * アクションのShow, Close, ChangeStateの状態はここで管理する。
2077
- */
2078
- /**
2079
- * アクションが表示 (show) された後にフックする関数
2080
- *
2081
- * @param fn - 呼び出されるフック関数
2082
- *
2083
- * @public
2084
- */
2085
- function onShow(fn) {
2086
- let { onShowHandlers } = getInternalHandlers();
2087
- if (!onShowHandlers) {
2088
- onShowHandlers = [];
2089
- }
2090
- onShowHandlers.push(fn);
2091
- setInternalHandlers({ onShowHandlers });
2092
- }
2093
- /**
2094
- * アクションがクローズ (close) される前にフックする関数
2095
- *
2096
- * @param fn - 呼び出されるフック関数
2097
- *
2098
- * @public
2099
- */
2100
- function onClose(fn) {
2101
- let { onCloseHandlers } = getInternalHandlers();
2102
- if (!onCloseHandlers) {
2103
- onCloseHandlers = [];
2104
- }
2105
- onCloseHandlers.push(fn);
2106
- setInternalHandlers({ onCloseHandlers });
2107
- }
2108
- /**
2109
- * アクションのステートが変更された (changeState) 後にフックする関数
2110
- *
2111
- * @param fn - 呼び出されるフック関数
2112
- *
2113
- * @public
2114
- */
2115
- function onChangeState(fn) {
2116
- let { onChangeStateHandlers } = getInternalHandlers();
2117
- if (!onChangeStateHandlers) {
2118
- onChangeStateHandlers = [];
2119
- }
2120
- onChangeStateHandlers.push(fn);
2121
- setInternalHandlers({ onChangeStateHandlers });
2122
- }
2123
- /**
2124
- * アクションを表示する
2125
- *
2126
- * @public
2127
- */
2128
- function showAction() {
2129
- const event = new CustomEvent(ACTION_SHOW_EVENT, { detail: { trigger: 'custom' } });
2130
- window.dispatchEvent(event);
2131
- }
2132
- /**
2133
- * アクションを閉じる
2134
- *
2135
- * @param trigger - 閉じた時のトリガー。デフォルト `'none'`
2136
- *
2137
- * @public
2138
- */
2139
- function closeAction(trigger = 'none') {
2140
- const event = new CustomEvent(ACTION_CLOSE_EVENT, { detail: { trigger } });
2141
- window.dispatchEvent(event);
2142
- }
2143
- /**
2144
- * アクションに CSS を適用する
2145
- *
2146
- * @param css - 適用する CSS
2147
- *
2148
- * @returns 適用された style 要素を返す Promise
2149
- *
2150
- * @public
2151
- */
2152
- async function applyCss(css) {
2153
- return new Promise((resolve, reject) => {
2154
- const style = document.createElement('style');
2155
- style.textContent = css;
2156
- const shadowRoot = getActionRoot();
2157
- if (!shadowRoot)
2158
- return;
2159
- shadowRoot.append(style);
2160
- style.addEventListener('load', () => resolve(style));
2161
- style.addEventListener('error', () => reject(style));
2162
- });
2163
- }
2164
- async function fixFontFaceIssue(href, cssRules) {
2165
- const css = new CSSStyleSheet();
2166
- // @ts-ignore
2167
- await css.replace(cssRules);
2168
- const rules = [];
2169
- const fixedRules = [];
2170
- Array.from(css.cssRules).forEach(cssRule => {
2171
- if (cssRule.type !== 5) {
2172
- rules.push(cssRule.cssText);
2173
- }
2174
- // type 5 is @font-face
2175
- const split = href.split('/');
2176
- const stylePath = split.slice(0, split.length - 1).join('/');
2177
- const cssText = cssRule.cssText;
2178
- const newCssText = cssText.replace(
2179
- // relative paths
2180
- /url\s*\(\s*['"]?(?!((\/)|((?:https?:)?\/\/)|(?:data:?:)))([^'")]+)['"]?\s*\)/g, `url("${stylePath}/$4")`);
2181
- if (cssText === newCssText)
2182
- return;
2183
- fixedRules.push(newCssText);
2184
- });
2185
- return [rules.join('\n'), fixedRules.join('\n')];
2186
- }
2187
- /**
2188
- * アクションにグローバルなスタイルを読み込む
2189
- *
2190
- * @param href - style ファイルのリンク URL
2191
- *
2192
- * @public
2193
- */
2194
- async function loadStyle(href) {
2195
- const sr = getActionRoot();
2196
- if (!sr)
2197
- return;
2198
- let cssRules = '';
2199
- try {
2200
- const res = await fetch(href);
2201
- cssRules = await res.text();
2202
- }
2203
- catch (_) {
2204
- // pass
2205
- }
2206
- if (!cssRules)
2207
- return;
2208
- // Chromeのバグで、Shadow Rootの@font-faceを絶対パスで指定する必要がある
2209
- // @see https://stackoverflow.com/a/63717709
2210
- const [rules, fontFaceRules] = await fixFontFaceIssue(href, cssRules);
2211
- const css = new CSSStyleSheet();
2212
- // @ts-ignore
2213
- await css.replace(rules);
2214
- const fontFaceCss = new CSSStyleSheet();
2215
- // @ts-ignore
2216
- await fontFaceCss.replace(fontFaceRules);
2217
- // @ts-ignore
2218
- sr.adoptedStyleSheets = [...sr.adoptedStyleSheets, css, fontFaceCss];
2219
- // Chromeのバグで、ページとShadow Rootの両方に、@font-faceを設定する必要がある
2220
- // @see https://stackoverflow.com/a/63717709
2221
- // @ts-ignore
2222
- document.adoptedStyleSheets = [...document.adoptedStyleSheets, css, fontFaceCss];
2223
- }
2224
- // @internal
2225
- function getCssVariables(data) {
2226
- return Object.entries(data)
2227
- .filter(([key, value]) => {
2228
- return ['string', 'number'].includes(typeof value) && key.startsWith('--');
2229
- })
2230
- .map(([key, value]) => `${key}:${value}`)
2231
- .join(';');
2232
- }
2233
- /**
2234
- * アクションのルートの DOM 要素を取得する
2235
- *
2236
- * @returns アクションがルートの DOM 要素 を持つ場合は DOM 要素を返します。ない場合は `null` を返します
2237
- *
2238
- * @public
2239
- */
2240
- function getActionRoot() {
2241
- const root = document.querySelector(`.${KARTE_ACTION_ROOT}[data-${KARTE_ACTION_RID}='${actionId}']`);
2242
- if (!root?.shadowRoot) {
2243
- return null;
2244
- }
2245
- return root.shadowRoot;
2246
- }
2247
- /** @internal */
2248
- function ensureActionRoot() {
2249
- const systemConfig = getSystem();
2250
- const rootAttrs = {
2251
- class: `${KARTE_ACTION_ROOT} ${KARTE_MODAL_ROOT}`,
2252
- [`data-${KARTE_ACTION_RID}`]: actionId,
2253
- [`data-${KARTE_ACTION_SHORTEN_ID}`]: systemConfig.shortenId
2254
- ? systemConfig.shortenId
2255
- : ALL_ACTION_SHORTEN_ID,
2256
- style: { display: 'block' },
2257
- };
2258
- let el = document.querySelector(`.${KARTE_MODAL_ROOT}[data-${KARTE_ACTION_RID}='${actionId}']`);
2259
- if (el == null) {
2260
- el = h('div', rootAttrs);
2261
- document.body.appendChild(el);
2262
- }
2263
- const isShadow = !!document.body.attachShadow;
2264
- if (isShadow) {
2265
- return el.shadowRoot ?? el.attachShadow({ mode: 'open' });
2266
- }
2267
- else {
2268
- return el;
2269
- }
2270
- }
2271
- /**
2272
- * 非推奨
2273
- *
2274
- * @deprecated 非推奨
2275
- *
2276
- * @internal
2277
- */
2278
- const show = showAction;
2279
- /**
2280
- * 非推奨
2281
- *
2282
- * @deprecated 非推奨
2283
- *
2284
- * @internal
2285
- */
2286
- const close = closeAction;
2287
- /**
2288
- * 非推奨
2289
- *
2290
- * @deprecated 非推奨
2291
- *
2292
- * @internal
2293
- */
2294
- const ensureModalRoot = ensureActionRoot;
2295
- /**
2296
- * 非推奨
2297
- *
2298
- * @deprecated 非推奨
2299
- *
2300
- * @internal
2301
- */
2302
- function createApp(App, options = {
2303
- send: () => { },
2304
- publish: () => { },
2305
- props: {},
2306
- variables: {},
2307
- localVariablesQuery: undefined,
2308
- context: { api_key: '' },
2309
- }) {
2310
- let app = null;
2311
- const close = () => {
2312
- if (app) {
2313
- {
2314
- // @ts-ignore -- Svelte3 では `unmount` は存在しない
2315
- svelte.unmount(app);
2316
- }
2317
- app = null;
2318
- }
2319
- };
2320
- const appArgs = {
2321
- target: null,
2322
- props: {
2323
- send: options.send,
2324
- publish: options.publish,
2325
- close,
2326
- data: {
2327
- ...options.props,
2328
- ...options.variables,
2329
- },
2330
- },
2331
- };
2332
- const win = ensureModalRoot();
2333
- appArgs.target = win;
2334
- return {
2335
- close,
2336
- show: () => {
2337
- if (app) {
2338
- return;
2339
- }
2340
- options.send('message_open');
2341
- app = // @ts-ignore -- Svelte3 では `mount` は存在しない
2342
- svelte.mount(App, appArgs)
2343
- ;
2344
- },
2345
- };
2346
- }
2347
- /**
2348
- * 非推奨
2349
- *
2350
- * @deprecated 非推奨
2351
- *
2352
- * @internal
2353
- */
2354
- function createFog({ color = '#000', opacity = '50%', zIndex = 999, onclick, }) {
2355
- const root = ensureModalRoot();
2356
- if (root.querySelector('.__krt-fog')) {
2357
- return { fog: null, close: () => { } };
2358
- }
2359
- const fog = document.createElement('div');
2360
- fog.className = '__krt-fog';
2361
- Object.assign(fog.style, {
2362
- position: 'fixed',
2363
- left: 0,
2364
- top: 0,
2365
- width: '100%',
2366
- height: '100%',
2367
- 'z-index': zIndex,
2368
- 'background-color': color,
2369
- opacity,
2370
- });
2371
- const close = () => {
2372
- onclick();
2373
- fog.remove();
2374
- };
2375
- fog.onclick = close;
2376
- root.appendChild(fog);
2377
- return { fog, close };
2378
- }
2379
-
2380
2467
  const USER_ID_VARIABLE_NAME = '__karte_form_identify_user_id';
2381
2468
  const MAX_LENGTH_FREE_ANSWER = 2000;
2382
2469
  function createAnswerValue(value) {
@@ -2849,9 +2936,11 @@ function Header($$anchor, $$props) {
2849
2936
  $fonts()
2850
2937
  ),
2851
2938
  () => {
2852
- {
2939
+ if (isPreview()) {
2853
2940
  // フォントのロードが遅れてエディタのプレビューがガタつく対策
2854
2941
  $.set(googleFontUrl, makeGoogleFontUrl(Fonts.filter((font) => font !== SYSTEM_FONT)));
2942
+ } else if ($fonts().length > 0) {
2943
+ $.set(googleFontUrl, makeGoogleFontUrl($fonts()));
2855
2944
  }
2856
2945
  }
2857
2946
  );
@@ -3362,6 +3451,54 @@ const execOnClickOperation = (onClickOperation) => {
3362
3451
  bootChat(...onClickOperation.args)();
3363
3452
  }
3364
3453
  };
3454
+ function getAnimation(animation) {
3455
+ switch (animation.type) {
3456
+ case 'fade':
3457
+ return `opacity: ${animation.progress}`;
3458
+ case 'bounce': {
3459
+ const translateX = animation.x;
3460
+ const translateY = animation.y;
3461
+ return `transform: translate3d(${translateX}%, ${translateY}%, 0) scale(${animation.progress});`;
3462
+ }
3463
+ case 'slide-down': {
3464
+ const translateX = animation.x;
3465
+ const translateY = animation.y - 100 * (1 - animation.progress);
3466
+ return `transform: translate3d(${translateX}%, ${translateY}%, 0);`;
3467
+ }
3468
+ case 'slide-up': {
3469
+ const translateX = animation.x;
3470
+ const translateY = animation.y + 100 * (1 - animation.progress);
3471
+ return `transform: translate3d(${translateX}%, ${translateY}%, 0);`;
3472
+ }
3473
+ case 'slide-left': {
3474
+ const translateX = animation.x + 100 * (1 - animation.progress);
3475
+ const translateY = animation.y;
3476
+ return `transform: translate3d(${translateX}%, ${translateY}%, 0);`;
3477
+ }
3478
+ case 'slide-right': {
3479
+ const translateX = animation.x - 100 * (1 - animation.progress);
3480
+ const translateY = animation.y;
3481
+ return `transform: translate3d(${translateX}%, ${translateY}%, 0);`;
3482
+ }
3483
+ case 'none': {
3484
+ const translateX = animation.x;
3485
+ const translateY = animation.y;
3486
+ return `transform: translate3d(${translateX}%, ${translateY}%, 0);`;
3487
+ }
3488
+ default:
3489
+ console.warn(`[action-sdk] invalid '${animation}', so we use 'transform: none' instead`);
3490
+ return 'transform: none';
3491
+ }
3492
+ }
3493
+ const EASING = {
3494
+ fade: linear,
3495
+ bounce: elasticOut,
3496
+ 'slide-down': cubicOut,
3497
+ 'slide-up': cubicOut,
3498
+ 'slide-left': cubicOut,
3499
+ 'slide-right': cubicOut,
3500
+ none: linear,
3501
+ };
3365
3502
  /**
3366
3503
  * The function to activate svelte animation.
3367
3504
  *
@@ -3373,9 +3510,23 @@ const execOnClickOperation = (onClickOperation) => {
3373
3510
  * @internal
3374
3511
  */
3375
3512
  function customAnimation(node, { transforms, animationStyle, delay = 0, duration = 1000 }) {
3376
- {
3513
+ if (!isOnSite()) {
3377
3514
  return {};
3378
3515
  }
3516
+ let [x, y] = [0, 0];
3517
+ for (const { query, x: tx, y: ty } of transforms) {
3518
+ if (query == null || window.matchMedia(query).matches) {
3519
+ x = tx;
3520
+ y = ty;
3521
+ break;
3522
+ }
3523
+ }
3524
+ return {
3525
+ delay,
3526
+ duration,
3527
+ easing: EASING[animationStyle],
3528
+ css: (progress) => getAnimation({ type: animationStyle, x, y, progress }),
3529
+ };
3379
3530
  }
3380
3531
 
3381
3532
  const getHref = (onClick) => {
@@ -6242,7 +6393,6 @@ function Modal($$anchor, $$props) {
6242
6393
  let closeEventValue = $.prop($$props, 'closeEventValue', 8, null);
6243
6394
  let layerId = $.prop($$props, 'layerId', 8, '');
6244
6395
  const { brandKit } = useBrandKit();
6245
- const isCanvasPreview = (document.querySelector('#preview')?.getAttribute('data-canvas-preview') ?? 'false') === 'true';
6246
6396
  // モーダル背景の設定
6247
6397
  const isExistBackgroundOverlayValue = placement() && placement().backgroundOverlay !== undefined;
6248
6398
  let backgroundOverlay = $.mutable_state(DefaultModalPlacement.backgroundOverlay);
@@ -6288,7 +6438,7 @@ function Modal($$anchor, $$props) {
6288
6438
  $.deep_read_state(breakPoint())
6289
6439
  ),
6290
6440
  () => {
6291
- if (!isCanvasPreview && isExistBackgroundOverlayValue) {
6441
+ if (!isCanvasPreview() && isExistBackgroundOverlayValue) {
6292
6442
  $.set(backgroundOverlay, placement().backgroundOverlay);
6293
6443
  }
6294
6444
 
@@ -6394,7 +6544,7 @@ function Modal($$anchor, $$props) {
6394
6544
  // 表示位置のスタイルの設定
6395
6545
  let position = DefaultModalPlacement.position;
6396
6546
 
6397
- if (!isCanvasPreview && placement() && placement().position !== null) {
6547
+ if (!isCanvasPreview() && placement() && placement().position !== null) {
6398
6548
  position = placement().position;
6399
6549
  }
6400
6550
 
@@ -6411,7 +6561,7 @@ function Modal($$anchor, $$props) {
6411
6561
  $.set(transforms, []);
6412
6562
 
6413
6563
  DEVICE_IDS.forEach((deviceId) => {
6414
- if (!isCanvasPreview && useBreakPoint()) {
6564
+ if (!isCanvasPreview() && useBreakPoint()) {
6415
6565
  const positionWithBp = breakPoint()[deviceId]?.placement?.position;
6416
6566
 
6417
6567
  $.get(transforms).push({
@@ -6447,7 +6597,7 @@ function Modal($$anchor, $$props) {
6447
6597
  () => {
6448
6598
  let margin = DefaultModalPlacement.margin;
6449
6599
 
6450
- if (!isCanvasPreview && placement() && placement().margin !== null) {
6600
+ if (!isCanvasPreview() && placement() && placement().margin !== null) {
6451
6601
  margin = placement().margin;
6452
6602
  }
6453
6603
 
@@ -6458,7 +6608,7 @@ function Modal($$anchor, $$props) {
6458
6608
  }
6459
6609
 
6460
6610
  DEVICE_IDS.forEach((deviceId) => {
6461
- if (!isCanvasPreview && useBreakPoint()) {
6611
+ if (!isCanvasPreview() && useBreakPoint()) {
6462
6612
  const marginWithBp = breakPoint()[deviceId]?.placement?.margin;
6463
6613
 
6464
6614
  marginStyle = getMarginStyle(marginWithBp);
@@ -6572,7 +6722,7 @@ function Modal($$anchor, $$props) {
6572
6722
  };
6573
6723
 
6574
6724
  $.if(node, ($$render) => {
6575
- if (isCanvasPreview) $$render(consequent); else $$render(alternate, false);
6725
+ if (isCanvasPreview()) $$render(consequent); else $$render(alternate, false);
6576
6726
  });
6577
6727
  }
6578
6728