UNPKG

one

Version:

One is a new React Framework that makes Vite serve both native and web.

552 lines 26.4 kB
var import_vitest = require("vitest"); var import_react_native = require("react-native-web"); var import_StackHeaderTitle = require("../StackHeaderTitle.cjs"); var import_StackHeaderLeft = require("../StackHeaderLeft.cjs"); var import_StackHeaderRight = require("../StackHeaderRight.cjs"); var import_StackHeaderBackButton = require("../StackHeaderBackButton.cjs"); var import_StackHeaderSearchBar = require("../StackHeaderSearchBar.cjs"); var import_StackHeaderComponent = require("../StackHeaderComponent.cjs"); var import_StackScreen = require("../StackScreen.cjs"); var import__ = require("../index.cjs"); var import_jsx_runtime = require("react/jsx-runtime"); (0, import_vitest.describe)("Stack Header Composition", () => { (0, import_vitest.describe)("StackHeaderTitle", () => { (0, import_vitest.it)("sets title from children", () => { const result = (0, import_StackHeaderTitle.appendStackHeaderTitlePropsToOptions)({}, { children: "My Title" }); (0, import_vitest.expect)(result.title).toBe("My Title"); }); (0, import_vitest.it)("sets headerLargeTitle when large is true", () => { const result = (0, import_StackHeaderTitle.appendStackHeaderTitlePropsToOptions)({}, { large: true }); (0, import_vitest.expect)(result.headerLargeTitle).toBe(true); }); (0, import_vitest.it)("sets headerTitleAlign from style.textAlign", () => { const result = (0, import_StackHeaderTitle.appendStackHeaderTitlePropsToOptions)({}, { style: { textAlign: "center" } }); (0, import_vitest.expect)(result.headerTitleAlign).toBe("center"); }); (0, import_vitest.it)("converts numeric fontWeight to string", () => { const result = (0, import_StackHeaderTitle.appendStackHeaderTitlePropsToOptions)({}, { style: { fontWeight: "700" } }); (0, import_vitest.expect)(result.headerTitleStyle).toMatchObject({ fontWeight: "700" }); }); (0, import_vitest.it)("preserves existing options", () => { const result = (0, import_StackHeaderTitle.appendStackHeaderTitlePropsToOptions)({ animation: "slide_from_right" }, { children: "Title" }); (0, import_vitest.expect)(result.animation).toBe("slide_from_right"); (0, import_vitest.expect)(result.title).toBe("Title"); }); (0, import_vitest.it)("sets headerTransparent only on iOS when large is true", () => { const originalOS = import_react_native.Platform.OS; import_react_native.Platform.OS = "ios"; const iosResult = (0, import_StackHeaderTitle.appendStackHeaderTitlePropsToOptions)({}, { large: true }); (0, import_vitest.expect)(iosResult.headerTransparent).toBe(true); import_react_native.Platform.OS = "android"; const androidResult = (0, import_StackHeaderTitle.appendStackHeaderTitlePropsToOptions)({}, { large: true }); (0, import_vitest.expect)(androidResult.headerTransparent).toBeUndefined(); import_react_native.Platform.OS = "web"; const webResult = (0, import_StackHeaderTitle.appendStackHeaderTitlePropsToOptions)({}, { large: true }); (0, import_vitest.expect)(webResult.headerTransparent).toBeUndefined(); import_react_native.Platform.OS = originalOS; }); }); (0, import_vitest.describe)("StackHeaderLeft", () => { (0, import_vitest.it)("does not set headerLeft without asChild", () => { const result = (0, import_StackHeaderLeft.appendStackHeaderLeftPropsToOptions)({}, { children: /* @__PURE__ */(0, import_jsx_runtime.jsx)("button", { children: "Back" }) }); (0, import_vitest.expect)(result.headerLeft).toBeUndefined(); }); (0, import_vitest.it)("sets headerLeft with asChild", () => { const CustomButton = () => /* @__PURE__ */(0, import_jsx_runtime.jsx)("button", { children: "Back" }); const result = (0, import_StackHeaderLeft.appendStackHeaderLeftPropsToOptions)({}, { asChild: true, children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(CustomButton, {}) }); (0, import_vitest.expect)(result.headerLeft).toBeDefined(); (0, import_vitest.expect)(typeof result.headerLeft).toBe("function"); }); (0, import_vitest.it)("sets headerLeft with asChild even without children", () => { const result = (0, import_StackHeaderLeft.appendStackHeaderLeftPropsToOptions)({}, { asChild: true }); (0, import_vitest.expect)(result.headerLeft).toBeDefined(); (0, import_vitest.expect)(typeof result.headerLeft).toBe("function"); }); (0, import_vitest.it)("preserves existing options when setting headerLeft", () => { const result = (0, import_StackHeaderLeft.appendStackHeaderLeftPropsToOptions)({ title: "Existing Title", animation: "slide_from_right" }, { asChild: true, children: /* @__PURE__ */(0, import_jsx_runtime.jsx)("button", { children: "Back" }) }); (0, import_vitest.expect)(result.title).toBe("Existing Title"); (0, import_vitest.expect)(result.animation).toBe("slide_from_right"); (0, import_vitest.expect)(result.headerLeft).toBeDefined(); }); (0, import_vitest.it)("headerLeft function returns children when called", () => { const BackButton = () => /* @__PURE__ */(0, import_jsx_runtime.jsx)("button", { children: "Back" }); const result = (0, import_StackHeaderLeft.appendStackHeaderLeftPropsToOptions)({}, { asChild: true, children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(BackButton, {}) }); const headerLeftResult = result.headerLeft?.({}); (0, import_vitest.expect)(headerLeftResult).toBeDefined(); }); }); (0, import_vitest.describe)("StackHeaderRight", () => { (0, import_vitest.it)("does not set headerRight without asChild", () => { const result = (0, import_StackHeaderRight.appendStackHeaderRightPropsToOptions)({}, { children: /* @__PURE__ */(0, import_jsx_runtime.jsx)("button", { children: "Action" }) }); (0, import_vitest.expect)(result.headerRight).toBeUndefined(); }); (0, import_vitest.it)("sets headerRight with asChild", () => { const CustomButton = () => /* @__PURE__ */(0, import_jsx_runtime.jsx)("button", { children: "Action" }); const result = (0, import_StackHeaderRight.appendStackHeaderRightPropsToOptions)({}, { asChild: true, children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(CustomButton, {}) }); (0, import_vitest.expect)(result.headerRight).toBeDefined(); (0, import_vitest.expect)(typeof result.headerRight).toBe("function"); }); (0, import_vitest.it)("sets headerRight with asChild even without children", () => { const result = (0, import_StackHeaderRight.appendStackHeaderRightPropsToOptions)({}, { asChild: true }); (0, import_vitest.expect)(result.headerRight).toBeDefined(); (0, import_vitest.expect)(typeof result.headerRight).toBe("function"); }); (0, import_vitest.it)("preserves existing options when setting headerRight", () => { const result = (0, import_StackHeaderRight.appendStackHeaderRightPropsToOptions)({ title: "Existing Title", headerLargeTitle: true }, { asChild: true, children: /* @__PURE__ */(0, import_jsx_runtime.jsx)("button", { children: "Action" }) }); (0, import_vitest.expect)(result.title).toBe("Existing Title"); (0, import_vitest.expect)(result.headerLargeTitle).toBe(true); (0, import_vitest.expect)(result.headerRight).toBeDefined(); }); (0, import_vitest.it)("headerRight function returns children when called", () => { const ActionButton = () => /* @__PURE__ */(0, import_jsx_runtime.jsx)("button", { children: "Action" }); const result = (0, import_StackHeaderRight.appendStackHeaderRightPropsToOptions)({}, { asChild: true, children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(ActionButton, {}) }); const headerRightResult = result.headerRight?.({}); (0, import_vitest.expect)(headerRightResult).toBeDefined(); }); }); (0, import_vitest.describe)("StackHeaderBackButton", () => { (0, import_vitest.it)("sets headerBackTitle from children", () => { const result = (0, import_StackHeaderBackButton.appendStackHeaderBackButtonPropsToOptions)({}, { children: "Go Back" }); (0, import_vitest.expect)(result.headerBackTitle).toBe("Go Back"); }); (0, import_vitest.it)("sets headerBackVisible to false when hidden", () => { const result = (0, import_StackHeaderBackButton.appendStackHeaderBackButtonPropsToOptions)({}, { hidden: true }); (0, import_vitest.expect)(result.headerBackVisible).toBe(false); }); (0, import_vitest.it)("sets headerBackButtonMenuEnabled", () => { const result = (0, import_StackHeaderBackButton.appendStackHeaderBackButtonPropsToOptions)({}, { withMenu: true }); (0, import_vitest.expect)(result.headerBackButtonMenuEnabled).toBe(true); }); (0, import_vitest.it)("sets headerBackButtonDisplayMode", () => { const result = (0, import_StackHeaderBackButton.appendStackHeaderBackButtonPropsToOptions)({}, { displayMode: "minimal" }); (0, import_vitest.expect)(result.headerBackButtonDisplayMode).toBe("minimal"); }); }); (0, import_vitest.describe)("StackHeaderSearchBar", () => { (0, import_vitest.it)("sets headerSearchBarOptions with placeholder", () => { const result = (0, import_StackHeaderSearchBar.appendStackHeaderSearchBarPropsToOptions)({}, { placeholder: "Search..." }); (0, import_vitest.expect)(result.headerSearchBarOptions).toMatchObject({ placeholder: "Search..." }); }); (0, import_vitest.it)("sets headerSearchBarOptions with autoCapitalize", () => { const result = (0, import_StackHeaderSearchBar.appendStackHeaderSearchBarPropsToOptions)({}, { autoCapitalize: "none" }); (0, import_vitest.expect)(result.headerSearchBarOptions).toMatchObject({ autoCapitalize: "none" }); }); (0, import_vitest.it)("sets headerSearchBarOptions with multiple props", () => { const result = (0, import_StackHeaderSearchBar.appendStackHeaderSearchBarPropsToOptions)({}, { placeholder: "Search articles...", autoCapitalize: "words", hideWhenScrolling: true, obscureBackground: false }); (0, import_vitest.expect)(result.headerSearchBarOptions).toMatchObject({ placeholder: "Search articles...", autoCapitalize: "words", hideWhenScrolling: true, obscureBackground: false }); }); (0, import_vitest.it)("preserves existing options when setting search bar", () => { const result = (0, import_StackHeaderSearchBar.appendStackHeaderSearchBarPropsToOptions)({ title: "Articles", headerLargeTitle: true }, { placeholder: "Search..." }); (0, import_vitest.expect)(result.title).toBe("Articles"); (0, import_vitest.expect)(result.headerLargeTitle).toBe(true); (0, import_vitest.expect)(result.headerSearchBarOptions).toMatchObject({ placeholder: "Search..." }); }); (0, import_vitest.it)("sets headerSearchBarOptions with placement prop", () => { const result = (0, import_StackHeaderSearchBar.appendStackHeaderSearchBarPropsToOptions)({}, { placeholder: "Search...", placement: "stacked" }); (0, import_vitest.expect)(result.headerSearchBarOptions).toMatchObject({ placeholder: "Search...", placement: "stacked" }); }); (0, import_vitest.it)("sets empty headerSearchBarOptions when no props", () => { const result = (0, import_StackHeaderSearchBar.appendStackHeaderSearchBarPropsToOptions)({}, {}); (0, import_vitest.expect)(result.headerSearchBarOptions).toBeDefined(); (0, import_vitest.expect)(result.headerSearchBarOptions).toEqual({}); }); }); (0, import_vitest.describe)("StackHeaderComponent", () => { (0, import_vitest.it)("sets headerShown false when hidden", () => { const result = (0, import_StackHeaderComponent.appendStackHeaderPropsToOptions)({}, { hidden: true }); (0, import_vitest.expect)(result.headerShown).toBe(false); }); (0, import_vitest.it)("sets headerBlurEffect", () => { const result = (0, import_StackHeaderComponent.appendStackHeaderPropsToOptions)({}, { blurEffect: "regular" }); (0, import_vitest.expect)(result.headerBlurEffect).toBe("regular"); }); (0, import_vitest.it)("sets headerShadowVisible false when shadowColor is transparent", () => { const result = (0, import_StackHeaderComponent.appendStackHeaderPropsToOptions)({}, { style: { shadowColor: "transparent" } }); (0, import_vitest.expect)(result.headerShadowVisible).toBe(false); }); (0, import_vitest.it)("sets headerTransparent when backgroundColor is transparent", () => { const result = (0, import_StackHeaderComponent.appendStackHeaderPropsToOptions)({}, { style: { backgroundColor: "transparent" } }); (0, import_vitest.expect)(result.headerTransparent).toBe(true); (0, import_vitest.expect)(result.headerStyle).toMatchObject({ backgroundColor: "transparent" }); }); (0, import_vitest.it)("sets headerTransparent with SearchBar (user controls via options if needed)", () => { const result = (0, import_StackHeaderComponent.appendStackHeaderPropsToOptions)({}, { style: { backgroundColor: "transparent" }, children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_StackHeaderSearchBar.StackHeaderSearchBar, { placeholder: "Search..." }) }); (0, import_vitest.expect)(result.headerTransparent).toBe(true); (0, import_vitest.expect)(result.headerSearchBarOptions).toMatchObject({ placeholder: "Search..." }); }); (0, import_vitest.it)("processes child Title component", () => { const result = (0, import_StackHeaderComponent.appendStackHeaderPropsToOptions)({}, { children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_StackHeaderTitle.StackHeaderTitle, { large: true, children: "Test Title" }) }); (0, import_vitest.expect)(result.title).toBe("Test Title"); (0, import_vitest.expect)(result.headerLargeTitle).toBe(true); }); (0, import_vitest.it)("processes child BackButton component", () => { const result = (0, import_StackHeaderComponent.appendStackHeaderPropsToOptions)({}, { children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_StackHeaderBackButton.StackHeaderBackButton, { hidden: true, children: "Back" }) }); (0, import_vitest.expect)(result.headerBackTitle).toBe("Back"); (0, import_vitest.expect)(result.headerBackVisible).toBe(false); }); (0, import_vitest.it)("processes multiple children", () => { const result = (0, import_StackHeaderComponent.appendStackHeaderPropsToOptions)({}, { children: [/* @__PURE__ */(0, import_jsx_runtime.jsx)(import_StackHeaderTitle.StackHeaderTitle, { large: true, children: "My Screen" }, "title"), /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_StackHeaderBackButton.StackHeaderBackButton, { hidden: true }, "back")] }); (0, import_vitest.expect)(result.title).toBe("My Screen"); (0, import_vitest.expect)(result.headerLargeTitle).toBe(true); (0, import_vitest.expect)(result.headerBackVisible).toBe(false); }); (0, import_vitest.it)("processes child Left component", () => { const result = (0, import_StackHeaderComponent.appendStackHeaderPropsToOptions)({}, { children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_StackHeaderLeft.StackHeaderLeft, { asChild: true, children: /* @__PURE__ */(0, import_jsx_runtime.jsx)("button", { children: "Back" }) }) }); (0, import_vitest.expect)(result.headerLeft).toBeDefined(); (0, import_vitest.expect)(typeof result.headerLeft).toBe("function"); }); (0, import_vitest.it)("processes child Right component", () => { const result = (0, import_StackHeaderComponent.appendStackHeaderPropsToOptions)({}, { children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_StackHeaderRight.StackHeaderRight, { asChild: true, children: /* @__PURE__ */(0, import_jsx_runtime.jsx)("button", { children: "Action" }) }) }); (0, import_vitest.expect)(result.headerRight).toBeDefined(); (0, import_vitest.expect)(typeof result.headerRight).toBe("function"); }); (0, import_vitest.it)("processes child SearchBar component", () => { const result = (0, import_StackHeaderComponent.appendStackHeaderPropsToOptions)({}, { children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_StackHeaderSearchBar.StackHeaderSearchBar, { placeholder: "Search..." }) }); (0, import_vitest.expect)(result.headerSearchBarOptions).toMatchObject({ placeholder: "Search..." }); }); (0, import_vitest.it)("processes all child components together", () => { const result = (0, import_StackHeaderComponent.appendStackHeaderPropsToOptions)({}, { children: [/* @__PURE__ */(0, import_jsx_runtime.jsx)(import_StackHeaderTitle.StackHeaderTitle, { large: true, children: "Articles" }, "title"), /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_StackHeaderLeft.StackHeaderLeft, { asChild: true, children: /* @__PURE__ */(0, import_jsx_runtime.jsx)("button", { children: "Back" }) }, "left"), /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_StackHeaderRight.StackHeaderRight, { asChild: true, children: /* @__PURE__ */(0, import_jsx_runtime.jsx)("button", { children: "More" }) }, "right"), /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_StackHeaderSearchBar.StackHeaderSearchBar, { placeholder: "Search articles..." }, "search"), /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_StackHeaderBackButton.StackHeaderBackButton, { displayMode: "minimal" }, "back")] }); (0, import_vitest.expect)(result.title).toBe("Articles"); (0, import_vitest.expect)(result.headerLargeTitle).toBe(true); (0, import_vitest.expect)(result.headerLeft).toBeDefined(); (0, import_vitest.expect)(result.headerRight).toBeDefined(); (0, import_vitest.expect)(result.headerSearchBarOptions).toMatchObject({ placeholder: "Search articles..." }); (0, import_vitest.expect)(result.headerBackButtonDisplayMode).toBe("minimal"); }); }); (0, import_vitest.describe)("StackScreen composition", () => { (0, import_vitest.it)("StackHeader is same reference as StackHeaderComponent", () => { (0, import_vitest.expect)(import__.StackHeader).toBe(import_StackHeaderComponent.StackHeaderComponent); }); (0, import_vitest.it)("merges options with Header composition", () => { const result = (0, import_StackScreen.appendScreenStackPropsToOptions)({ animation: "slide_from_right" }, { options: { gestureEnabled: true }, children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_StackHeaderComponent.StackHeaderComponent, { blurEffect: "regular", children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_StackHeaderTitle.StackHeaderTitle, { large: true, children: "Composed Title" }) }) }); (0, import_vitest.expect)(result.animation).toBe("slide_from_right"); (0, import_vitest.expect)(result.gestureEnabled).toBe(true); (0, import_vitest.expect)(result.headerBlurEffect).toBe("regular"); (0, import_vitest.expect)(result.title).toBe("Composed Title"); (0, import_vitest.expect)(result.headerLargeTitle).toBe(true); }); (0, import_vitest.it)("works with StackHeader compound component (as used via Stack.Header)", () => { const result = (0, import_StackScreen.appendScreenStackPropsToOptions)({}, { children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(import__.StackHeader, { children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(import__.StackHeader.Title, { large: true, children: "Large Title Test" }) }) }); (0, import_vitest.expect)(result.title).toBe("Large Title Test"); (0, import_vitest.expect)(result.headerLargeTitle).toBe(true); }); (0, import_vitest.it)("works with StackHeader compound component with Left child", () => { const result = (0, import_StackScreen.appendScreenStackPropsToOptions)({}, { children: /* @__PURE__ */(0, import_jsx_runtime.jsxs)(import__.StackHeader, { children: [/* @__PURE__ */(0, import_jsx_runtime.jsx)(import__.StackHeader.Title, { large: true, children: "Articles" }), /* @__PURE__ */(0, import_jsx_runtime.jsx)(import__.StackHeader.Left, { asChild: true, children: /* @__PURE__ */(0, import_jsx_runtime.jsx)("button", { children: "Back" }) })] }) }); (0, import_vitest.expect)(result.title).toBe("Articles"); (0, import_vitest.expect)(result.headerLargeTitle).toBe(true); (0, import_vitest.expect)(result.headerLeft).toBeDefined(); }); (0, import_vitest.it)("composition overrides options prop", () => { const result = (0, import_StackScreen.appendScreenStackPropsToOptions)({}, { options: { title: "Options Title" }, children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_StackHeaderComponent.StackHeaderComponent, { children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_StackHeaderTitle.StackHeaderTitle, { children: "Composed Title" }) }) }); (0, import_vitest.expect)(result.title).toBe("Composed Title"); }); (0, import_vitest.it)("works with StackHeader compound component with Right child", () => { const result = (0, import_StackScreen.appendScreenStackPropsToOptions)({}, { children: /* @__PURE__ */(0, import_jsx_runtime.jsxs)(import__.StackHeader, { children: [/* @__PURE__ */(0, import_jsx_runtime.jsx)(import__.StackHeader.Title, { children: "Settings" }), /* @__PURE__ */(0, import_jsx_runtime.jsx)(import__.StackHeader.Right, { asChild: true, children: /* @__PURE__ */(0, import_jsx_runtime.jsx)("button", { children: "Save" }) })] }) }); (0, import_vitest.expect)(result.title).toBe("Settings"); (0, import_vitest.expect)(result.headerRight).toBeDefined(); }); (0, import_vitest.it)("works with StackHeader compound component with SearchBar child", () => { const result = (0, import_StackScreen.appendScreenStackPropsToOptions)({}, { children: /* @__PURE__ */(0, import_jsx_runtime.jsxs)(import__.StackHeader, { children: [/* @__PURE__ */(0, import_jsx_runtime.jsx)(import__.StackHeader.Title, { large: true, children: "Articles" }), /* @__PURE__ */(0, import_jsx_runtime.jsx)(import__.StackHeader.SearchBar, { placeholder: "Search articles..." })] }) }); (0, import_vitest.expect)(result.title).toBe("Articles"); (0, import_vitest.expect)(result.headerLargeTitle).toBe(true); (0, import_vitest.expect)(result.headerSearchBarOptions).toMatchObject({ placeholder: "Search articles..." }); }); (0, import_vitest.it)("works with full compositional setup", () => { const result = (0, import_StackScreen.appendScreenStackPropsToOptions)({}, { options: { animation: "slide_from_right" }, children: /* @__PURE__ */(0, import_jsx_runtime.jsxs)(import__.StackHeader, { blurEffect: "regular", children: [/* @__PURE__ */(0, import_jsx_runtime.jsx)(import__.StackHeader.Title, { large: true, children: "My App" }), /* @__PURE__ */(0, import_jsx_runtime.jsx)(import__.StackHeader.Left, { asChild: true, children: /* @__PURE__ */(0, import_jsx_runtime.jsx)("button", { children: "Menu" }) }), /* @__PURE__ */(0, import_jsx_runtime.jsx)(import__.StackHeader.Right, { asChild: true, children: /* @__PURE__ */(0, import_jsx_runtime.jsx)("button", { children: "Settings" }) }), /* @__PURE__ */(0, import_jsx_runtime.jsx)(import__.StackHeader.BackButton, { displayMode: "minimal" }), /* @__PURE__ */(0, import_jsx_runtime.jsx)(import__.StackHeader.SearchBar, { placeholder: "Search...", placement: "stacked" })] }) }); (0, import_vitest.expect)(result.animation).toBe("slide_from_right"); (0, import_vitest.expect)(result.headerBlurEffect).toBe("regular"); (0, import_vitest.expect)(result.title).toBe("My App"); (0, import_vitest.expect)(result.headerLargeTitle).toBe(true); (0, import_vitest.expect)(result.headerTransparent).toBeUndefined(); (0, import_vitest.expect)(result.headerLeft).toBeDefined(); (0, import_vitest.expect)(result.headerRight).toBeDefined(); (0, import_vitest.expect)(result.headerBackButtonDisplayMode).toBe("minimal"); (0, import_vitest.expect)(result.headerSearchBarOptions).toMatchObject({ placeholder: "Search...", placement: "stacked" }); }); }); });