Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions pos-ui-extension-cash-management/package.json.liquid
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{%- if flavor contains "react" -%}
{
"name": "{{ handle }}",
"private": true,
"version": "1.0.0",
"license": "UNLICENSED",
"dependencies": {
"react": "^18.0.0",
"@shopify/ui-extensions": "2025.10.x",
"@shopify/ui-extensions-react": "2025.10.x",
"react-reconciler": "0.29.0"
}{% if flavor contains "typescript" %},
"devDependencies": {
"@types/react": "^18.0.0"
}{% endif %}
}
{%- else -%}
{
"name": "{{ handle }}",
"private": true,
"version": "1.0.0",
"license": "UNLICENSED",
"dependencies": {
"@shopify/ui-extensions": "2025.10.x"
}
}
{%- endif -%}
28 changes: 28 additions & 0 deletions pos-ui-extension-cash-management/shopify.extension.toml.liquid
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# The version of APIs your extension will receive. Learn more:
# https://shopify.dev/docs/api/usage/versioning
api_version = "2025-10"

[[extensions]]
type = "ui_extension"
name = "{{ name }}"
{% if uid %}uid = "{{ uid }}"{% endif %}
handle = "{{ handle }}"
description = "A {{ flavor }} POS UI extension"

# Controls where in POS your extension will be injected,
# and the file that contains your extension’s source code.
[[extensions.targeting]]
module = "./src/Action.{{ srcFileExtension }}"
target = "pos.cash-tracking-session-details.action.render"

[[extensions.targeting]]
module = "./src/Block.{{ srcFileExtension }}"
target = "pos.cash-tracking-session-details.block.render"

[[extensions.targeting]]
module = "./src/MenuItem.{{ srcFileExtension }}"
target = "pos.cash-tracking-session-details.action.menu-item.render"

[[extensions.targeting]]
module = "./src/Banner.{{ srcFileExtension }}"
target = "pos.cash-tracking-session-details.block.render-before"
55 changes: 55 additions & 0 deletions pos-ui-extension-cash-management/src/Action.liquid
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
{%- if flavor contains "react" -%}
import React from 'react';

import {
Text,
Screen,
ScrollView,
Navigator,
reactExtension,
useApi,
} from '@shopify/ui-extensions-react/point-of-sale';

const Modal = () => {
{% if flavor contains "typescript" %}const api = useApi<"pos.cash-tracking-session-details.action.render">();
{% else %}const api = useApi();
{% endif %}
return (
<Navigator>
<Screen name="CashManagement" title="Cash Management">
<ScrollView>
<Text>This is a modal extension</Text>
</ScrollView>
</Screen>
</Navigator>
);
};

export default reactExtension('pos.cash-tracking-session-details.action.render', () => (
<Modal />
));
{%- else -%}
import {
Navigator,
Screen,
ScrollView,
Text,
extension,
} from '@shopify/ui-extensions/point-of-sale';

export default extension('pos.cash-tracking-session-details.action.render', (root, api) => {
const navigator = root.createComponent(Navigator);
const screen = root.createComponent(Screen, {
name: 'CashManagement',
title: 'Cash Management',
});
const scrollView = root.createComponent(ScrollView);
const text = root.createComponent(Text);

text.append('This is a modal extension');
scrollView.append(text);
screen.append(scrollView);
navigator.append(screen);
root.append(navigator);
});
{%- endif -%}
33 changes: 33 additions & 0 deletions pos-ui-extension-cash-management/src/Banner.liquid
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{%- if flavor contains "react" -%}
import React from 'react';

import {
Banner,
useApi,
reactExtension,
} from '@shopify/ui-extensions-react/point-of-sale';

const Banner = () => {
{% if flavor contains "typescript" %}const api = useApi<"pos.cash-tracking-session-details.block.render-before">();
{% else %}const api = useApi();
{% endif %}
{% raw %}return (
<Banner title="This is a banner extension" variant="alert" visible/>
);{% endraw %}
};

export default reactExtension('pos.cash-tracking-session-details.block.render-before', () => (
<Banner />
));
{%- else -%}
import {
Banner,
extension,
} from '@shopify/ui-extensions/point-of-sale';

export default extension('pos.cash-tracking-session-details.block.render-before', (root, api) => {
const banner = root.createComponent(Banner, { title: 'This is a banner extension', variant: 'alert', visible: true });

root.append(banner);
});
{%- endif -%}
51 changes: 51 additions & 0 deletions pos-ui-extension-cash-management/src/Block.liquid
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
{%- if flavor contains "react" -%}
import React from 'react';

import {
Text,
useApi,
reactExtension,
POSBlock,
POSBlockRow,
} from '@shopify/ui-extensions-react/point-of-sale';

const Block = () => {
{% if flavor contains "typescript" %}const api = useApi<"pos.cash-tracking-session-details.block.render">();
{% else %}const api = useApi();
{% endif %}
{% raw %}return (
<POSBlock action={{title: 'Open action', onPress: api.action.presentModal}}>
<POSBlockRow>
<Text>{'This is a block extension'}</Text>
</POSBlockRow>
</POSBlock>
);{% endraw %}
};

export default reactExtension('pos.cash-tracking-session-details.block.render', () => (
<Block />
));
{%- else -%}
import {
POSBlock,
Text,
POSBlockRow,
extension,
} from '@shopify/ui-extensions/point-of-sale';

export default extension('pos.cash-tracking-session-details.block.render', (root, api) => {
const block = root.createComponent(POSBlock, {
action: {title: 'Open action', onPress: api.action.presentModal},
});

const mainText = root.createComponent(Text);
mainText.append('This is a block extension');

const blockMainRow = root.createComponent(POSBlockRow);
blockMainRow.append(mainText);

block.append(blockMainRow);

root.append(block);
});
{%- endif -%}
35 changes: 35 additions & 0 deletions pos-ui-extension-cash-management/src/MenuItem.liquid
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{%- if flavor contains "react" -%}
import React from 'react';
import {
reactExtension,
Button,
useApi,
} from '@shopify/ui-extensions-react/point-of-sale';

const ButtonComponent = () => {
{% if flavor contains "typescript" %}const api = useApi<"pos.cash-tracking-session-details.action.menu-item.render">();
{% else %}const api = useApi();
{% endif %}
return <Button onPress={() => api.action.presentModal()} />;
};

export default reactExtension(
'pos.cash-tracking-session-details.action.menu-item.render',
() => <ButtonComponent />,
);
{%- else -%}
import {Button, extension} from '@shopify/ui-extensions/point-of-sale';

export default extension(
'pos.cash-tracking-session-details.action.menu-item.render',
(root, api) => {
const button = root.createComponent(Button, {
onPress: () => {
api.action.presentModal();
},
});

root.append(button);
},
);
{%- endif -%}
32 changes: 32 additions & 0 deletions templates.json
Original file line number Diff line number Diff line change
Expand Up @@ -974,6 +974,38 @@
}
]
},
{
"identifier": "pos_ui_cash_management",
"name": "POS UI cash management",
"defaultName": "pos-ui-cash-management",
"group": "UI extensions",
"supportLinks": [],
"url": "https://github.com/Shopify/extensions-templates",
"type": "pos_ui_extension",
"extensionPoints": [],
"supportedFlavors": [
{
"name": "JavaScript React",
"value": "react",
"path": "pos-ui-extension-cash-management"
},
{
"name": "JavaScript",
"value": "vanilla-js",
"path": "pos-ui-extension-cash-management"
},
{
"name": "TypeScript React",
"value": "typescript-react",
"path": "pos-ui-extension-cash-management"
},
{
"name": "TypeScript",
"value": "typescript",
"path": "pos-ui-extension-cash-management"
}
]
},
{
"identifier": "cart_checkout_validation",
"name": "Cart and checkout validation",
Expand Down