Skip to content
This repository was archived by the owner on Oct 20, 2023. It is now read-only.

Commit fcb74bb

Browse files
author
t-kelly
committedNov 9, 2017
Move scripts from shopify/slate
0 parents  commit fcb74bb

21 files changed

+1306
-0
lines changed
 

‎.gitignore

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# Compiled source #
2+
###################
3+
*.com
4+
*.class
5+
*.dll
6+
*.exe
7+
*.o
8+
*.so
9+
10+
# Packages #
11+
############
12+
# it's better to unpack these files and commit the raw source
13+
# git has its own built in compression methods
14+
*.7z
15+
*.dmg
16+
*.gz
17+
*.iso
18+
*.jar
19+
*.rar
20+
*.tar
21+
*.zip
22+
23+
# Logs and databases #
24+
######################
25+
*.log
26+
*.sql
27+
*.sqlite
28+
29+
# OS generated files #
30+
######################
31+
.DS_Store
32+
.DS_Store?
33+
._*
34+
.Spotlight-V100
35+
.Trashes
36+
ehthumbs.db
37+
Thumbs.db
38+
39+
# Custom #
40+
######################
41+
*.sass-cache*
42+
node_modules

‎CODE_OF_CONDUCT.md

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# Contributor Code of Conduct
2+
3+
As contributors and maintainers of this project, and in the interest of
4+
fostering an open and welcoming community, we pledge to respect all
5+
people who contribute through reporting issues, posting feature
6+
requests, updating documentation, submitting pull requests or patches,
7+
and other activities.
8+
9+
We are committed to making participation in this project a
10+
harassment-free experience for everyone, regardless of level of
11+
experience, gender, gender identity and expression, sexual orientation,
12+
disability, personal appearance, body size, race, ethnicity, age,
13+
religion, or nationality.
14+
15+
Examples of unacceptable behavior by participants include:
16+
17+
* The use of sexualized language or imagery
18+
* Personal attacks
19+
* Trolling or insulting/derogatory comments
20+
* Public or private harassment
21+
* Publishing other's private information, such as physical or electronic
22+
addresses, without explicit permission
23+
* Other unethical or unprofessional conduct
24+
25+
Project maintainers have the right and responsibility to remove, edit,
26+
or reject comments, commits, code, wiki edits, issues, and other
27+
contributions that are not aligned to this Code of Conduct, or to ban
28+
temporarily or permanently any contributor for other behaviors that they
29+
deem inappropriate, threatening, offensive, or harmful.
30+
31+
By adopting this Code of Conduct, project maintainers commit themselves
32+
to fairly and consistently applying these principles to every aspect of
33+
managing this project. Project maintainers who do not follow or enforce
34+
the Code of Conduct may be permanently removed from the project team.
35+
36+
This Code of Conduct applies both within project spaces and in public
37+
spaces when an individual is representing the project or its community.
38+
39+
Instances of abusive, harassing, or otherwise unacceptable behavior may
40+
be reported by contacting a project maintainer at <slate@shopify.com>. All complaints will be reviewed and investigated and will
41+
result in a response that is deemed necessary and appropriate to the
42+
circumstances. Maintainers are obligated to maintain confidentiality
43+
with regard to the reporter of an incident.
44+
45+
This Code of Conduct is adapted from the Contributor Covenant, version
46+
1.3.0, available from http://contributor-covenant.org/version/1/3/0/

‎LICENSE

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
The MIT License (MIT)
2+
3+
Copyright (c) 2016 Shopify Inc.
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in
13+
all copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21+
THE SOFTWARE.

‎README.md

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# theme-scripts

‎lerna.json

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"lerna": "2.5.1",
3+
"packages": ["packages/*"],
4+
"version": "1.0.0-alpha.0"
5+
}

‎package.json

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{
2+
"devDependencies": {
3+
"lerna": "^2.5.1"
4+
},
5+
"name": "theme-scripts",
6+
"version": "1.0.0-alpha.0",
7+
"description":
8+
"A collection of helpful script libraries that help you make better Shopify themes.",
9+
"main": "index.js",
10+
"scripts": {
11+
"test": "jest"
12+
},
13+
"repository": {
14+
"type": "git",
15+
"url": "git@github.com:Shopify/theme-scripts.git"
16+
},
17+
"keywords": ["Shopify"],
18+
"author": "Shopify Inc.",
19+
"license": "MIT"
20+
}

‎packages/theme-a11y/a11y.js

+106
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
/**
2+
* A11y Helpers
3+
* -----------------------------------------------------------------------------
4+
* A collection of useful functions that help make your theme more accessible
5+
* to users with visual impairments.
6+
*/
7+
8+
import $ from 'jquery';
9+
10+
/**
11+
* For use when focus shifts to a container rather than a link
12+
* eg for In-page links, after scroll, focus shifts to content area so that
13+
* next `tab` is where user expects if focusing a link, just $link.focus();
14+
*
15+
* @param {JQuery} $element - The element to be acted upon
16+
*/
17+
export function pageLinkFocus($element) {
18+
const focusClass = 'js-focus-hidden';
19+
20+
$element
21+
.first()
22+
.attr('tabIndex', '-1')
23+
.focus()
24+
.addClass(focusClass)
25+
.one('blur', callback);
26+
27+
function callback() {
28+
$element
29+
.first()
30+
.removeClass(focusClass)
31+
.removeAttr('tabindex');
32+
}
33+
}
34+
35+
/**
36+
* If there's a hash in the url, focus the appropriate element
37+
*/
38+
export function focusHash() {
39+
const hash = window.location.hash;
40+
41+
// is there a hash in the url? is it an element on the page?
42+
if (hash && document.getElementById(hash.slice(1))) {
43+
this.pageLinkFocus($(hash));
44+
}
45+
}
46+
47+
/**
48+
* When an in-page (url w/hash) link is clicked, focus the appropriate element
49+
*/
50+
export function bindInPageLinks() {
51+
$('a[href*=#]').on(
52+
'click',
53+
(evt) => {
54+
this.pageLinkFocus($(evt.currentTarget.hash));
55+
}
56+
);
57+
}
58+
59+
/**
60+
* Traps the focus in a particular container
61+
*
62+
* @param {object} options - Options to be used
63+
* @param {jQuery} options.$container - Container to trap focus within
64+
* @param {jQuery} options.$elementToFocus - Element to be focused when focus leaves container
65+
* @param {string} options.namespace - Namespace used for new focus event handler
66+
*/
67+
export function trapFocus(options) {
68+
const eventName = options.namespace
69+
? `focusin.${options.namespace}`
70+
: 'focusin';
71+
72+
if (!options.$elementToFocus) {
73+
options.$elementToFocus = options.$container;
74+
}
75+
76+
options.$container.attr('tabindex', '-1');
77+
options.$elementToFocus.focus();
78+
79+
$(document).on(eventName, (evt) => {
80+
if (
81+
options.$container[0] !== evt.target &&
82+
!options.$container.has(evt.target).length
83+
) {
84+
options.$container.focus();
85+
}
86+
});
87+
}
88+
89+
/**
90+
* Removes the trap of focus in a particular container
91+
*
92+
* @param {object} options - Options to be used
93+
* @param {jQuery} options.$container - Container to trap focus within
94+
* @param {string} options.namespace - Namespace used for new focus event handler
95+
*/
96+
export function removeTrapFocus(options) {
97+
const eventName = options.namespace
98+
? `focusin.${options.namespace}`
99+
: 'focusin';
100+
101+
if (options.$container && options.$container.length) {
102+
options.$container.removeAttr('tabindex');
103+
}
104+
105+
$(document).off(eventName);
106+
}

‎packages/theme-a11y/package.json

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"name": "@shopify/theme-a11y",
3+
"version": "1.0.0-alpha.1",
4+
"description":
5+
"A library of useful functions that help make your theme more accessible.",
6+
"main": "a11y.js",
7+
"repository": {
8+
"type": "git",
9+
"url": "git+https://github.com/Shopify/theme-scripts.git"
10+
},
11+
"keywords": ["slate", "a11y"],
12+
"author": "Shopify Inc.",
13+
"license": "MIT",
14+
"bugs": {
15+
"url": "https://github.com/Shopify/theme-scripts/issues"
16+
},
17+
"homepage": "https://github.com/Shopify/theme-scripts#readme",
18+
"peerDependencies": {
19+
"jquery": "3.x"
20+
}
21+
}

‎packages/theme-cart/cart.js

+129
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
/**
2+
* Cart Template Script
3+
* ------------------------------------------------------------------------------
4+
* A file that contains scripts highly couple code to the Cart template.
5+
*
6+
* @namespace cart
7+
*/
8+
9+
import $ from 'jquery';
10+
import find from 'lodash-es/find';
11+
12+
export function getCart() {
13+
return $.getJSON('/cart.js');
14+
}
15+
16+
export function updateNote(note) {
17+
return this._promiseChange({
18+
url: '/cart/update.js',
19+
dataType: 'json',
20+
data: {
21+
note: note || '',
22+
},
23+
});
24+
}
25+
26+
export function addItem(id, quantity) {
27+
return this._promiseChange({
28+
url: '/cart/add.js',
29+
dataType: 'json',
30+
data: {
31+
id,
32+
quantity: typeof quantity === 'undefined' ? 1 : quantity,
33+
},
34+
});
35+
}
36+
37+
export function addItemFromForm(data) {
38+
return this._promiseChange({
39+
url: '/cart/add.js',
40+
dataType: 'json',
41+
data,
42+
});
43+
}
44+
45+
export function removeItem(id) {
46+
return this._promiseChange({
47+
url: '/cart/change.js',
48+
dataType: 'json',
49+
data: {
50+
id,
51+
quantity: 0,
52+
},
53+
});
54+
}
55+
56+
export function changeItem(id, quantity) {
57+
const originalQuantity = parseInt(quantity, 10);
58+
const requestSettings = {
59+
url: '/cart/change.js',
60+
dataType: 'json',
61+
data: {
62+
id,
63+
quantity,
64+
},
65+
};
66+
67+
return this._promiseChange(requestSettings);
68+
}
69+
70+
export function saveLocalState(state) {
71+
if (_isLocalStorageSupported()) {
72+
localStorage.shopify_cart_state = JSON.stringify(state); // eslint-disable-line camelcase
73+
}
74+
75+
return state;
76+
}
77+
78+
export function getLocalState() {
79+
// eslint-disable-line consistent-return
80+
if (_isLocalStorageSupported()) {
81+
return JSON.parse(localStorage.shopify_cart_state || '');
82+
}
83+
}
84+
85+
export function cookiesEnabled() {
86+
let cookieEnabled = navigator.cookieEnabled;
87+
88+
if (!cookieEnabled) {
89+
document.cookie = 'testcookie';
90+
cookieEnabled = document.cookie.indexOf('testcookie') !== -1;
91+
}
92+
return cookieEnabled;
93+
}
94+
95+
function _promiseChange(parameters) {
96+
let promiseRequest = $.ajax(parameters);
97+
98+
// If offline, provide a rejected promise so that an error is thrown.
99+
if (navigator && !theme.isOnline) {
100+
promiseRequest = $.Deferred().reject();
101+
}
102+
103+
return (
104+
promiseRequest
105+
// Some cart API requests don't return the cart object. If there is no
106+
// cart object then get one before proceeding.
107+
.then(
108+
(state) => {
109+
if (typeof state.token === 'undefined') {
110+
return this.getCart();
111+
} else {
112+
return state;
113+
}
114+
}
115+
)
116+
.then(this.saveLocalState)
117+
);
118+
}
119+
120+
function _isLocalStorageSupported() {
121+
const mod = 'localStorageTest';
122+
try {
123+
localStorage.setItem(mod, mod);
124+
localStorage.removeItem(mod);
125+
return true;
126+
} catch (error) {
127+
return false;
128+
}
129+
}

‎packages/theme-cart/package.json

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"name": "@shopify/theme-cart",
3+
"version": "1.0.0-alpha.1",
4+
"description":
5+
"A library that helps theme developers integrate their projects with the Shopify Cart API",
6+
"main": "cart.js",
7+
"repository": {
8+
"type": "git",
9+
"url": "git+https://github.com/Shopify/theme-scripts.git"
10+
},
11+
"keywords": ["slate"],
12+
"author": "Shopify Inc.",
13+
"license": "MIT",
14+
"bugs": {
15+
"url": "https://github.com/Shopify/theme-scripts/issues"
16+
},
17+
"homepage": "https://github.com/Shopify/theme-scripts#readme",
18+
"peerDependencies": {
19+
"jquery": "3.x",
20+
"lodash-es": "4.x"
21+
}
22+
}

‎packages/theme-currency/currency.js

+69
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/**
2+
* Currency Helpers
3+
* -----------------------------------------------------------------------------
4+
* A collection of useful functions that help with currency formatting
5+
*
6+
* Current contents
7+
* - formatMoney - Takes an amount in cents and returns it as a formatted dollar value.
8+
*
9+
*/
10+
11+
const moneyFormat = '${{amount}}';
12+
13+
/**
14+
* Format money values based on your shop currency settings
15+
* @param {Number|string} cents - value in cents or dollar amount e.g. 300 cents
16+
* or 3.00 dollars
17+
* @param {String} format - shop money_format setting
18+
* @return {String} value - formatted value
19+
*/
20+
export function formatMoney(cents, format) {
21+
if (typeof cents === 'string') {
22+
cents = cents.replace('.', '');
23+
}
24+
let value = '';
25+
const placeholderRegex = /\{\{\s*(\w+)\s*\}\}/;
26+
const formatString = format || moneyFormat;
27+
28+
function formatWithDelimiters(
29+
number,
30+
precision = 2,
31+
thousands = ',',
32+
decimal = '.'
33+
) {
34+
if (isNaN(number) || number == null) {
35+
return 0;
36+
}
37+
38+
number = (number / 100.0).toFixed(precision);
39+
40+
const parts = number.split('.');
41+
const dollarsAmount = parts[0].replace(
42+
/(\d)(?=(\d\d\d)+(?!\d))/g,
43+
`$1${thousands}`
44+
);
45+
const centsAmount = parts[1] ? decimal + parts[1] : '';
46+
47+
return dollarsAmount + centsAmount;
48+
}
49+
50+
switch (formatString.match(placeholderRegex)[1]) {
51+
case 'amount':
52+
value = formatWithDelimiters(cents, 2);
53+
break;
54+
case 'amount_no_decimals':
55+
value = formatWithDelimiters(cents, 0);
56+
break;
57+
case 'amount_with_space_separator':
58+
value = formatWithDelimiters(cents, 2, ' ', '.');
59+
break;
60+
case 'amount_no_decimals_with_comma_separator':
61+
value = formatWithDelimiters(cents, 0, ',', '.');
62+
break;
63+
case 'amount_no_decimals_with_space_separator':
64+
value = formatWithDelimiters(cents, 0, ' ');
65+
break;
66+
}
67+
68+
return formatString.replace(placeholderRegex, value);
69+
}
+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import {formatMoney} from './currency';
2+
3+
describe('currency.formatMoney', () => {
4+
test('Formats a string of "10001" to a string of "$100.01"', () => {
5+
const value = formatMoney('10001');
6+
expect(value).toBe('$100.01');
7+
});
8+
9+
test('Formats a number of 10001 to a string of "$100.01"', () => {
10+
const value = formatMoney(10001);
11+
expect(value).toBe('$100.01');
12+
});
13+
14+
test('Formats a number of 1000001 to a string of "$10,000.01"', () => {
15+
const value = formatMoney(1000001);
16+
expect(value).toBe('$10,000.01');
17+
});
18+
19+
test('Formats a number 1000001 to a string of "$10 000.01"', () => {
20+
const value = formatMoney(1000001, '${{amount_with_space_separator}}');
21+
expect(value).toBe('$10 000.01');
22+
});
23+
24+
test('Formats a number 10001 to a string of "$100"', () => {
25+
const value = formatMoney(10001, '${{amount_no_decimals}}');
26+
expect(value).toBe('$100');
27+
});
28+
29+
test('Formats a number 1000001 to a string of "$10,000"', () => {
30+
const value = formatMoney(
31+
1000001,
32+
'${{amount_no_decimals_with_comma_separator}}'
33+
);
34+
expect(value).toBe('$10,000');
35+
});
36+
37+
test('Formats a number 1000001 to a string of "$10 000"', () => {
38+
const value = formatMoney(
39+
1000001,
40+
'${{amount_no_decimals_with_space_separator}}'
41+
);
42+
expect(value).toBe('$10 000');
43+
});
44+
});

‎packages/theme-currency/package.json

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"name": "@shopify/theme-currency",
3+
"version": "1.0.0-alpha.1",
4+
"description":
5+
"A library that helps with managing currencies in Shopify Themes",
6+
"main": "currency.js",
7+
"repository": {
8+
"type": "git",
9+
"url": "git+https://github.com/Shopify/theme-scripts.git"
10+
},
11+
"keywords": ["slate"],
12+
"author": "Shopify Inc.",
13+
"license": "MIT",
14+
"bugs": {
15+
"url": "https://github.com/Shopify/theme-scripts/issues"
16+
},
17+
"homepage": "https://github.com/Shopify/theme-scripts#readme"
18+
}

‎packages/theme-images/images.js

+82
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
/**
2+
* Image Helper Functions
3+
* -----------------------------------------------------------------------------
4+
* https://github.com/Shopify/slate.git.
5+
*
6+
*/
7+
8+
/**
9+
* Preloads an image in memory and uses the browsers cache to store it until needed.
10+
*
11+
* @param {Array} images - A list of image urls
12+
* @param {String} size - A shopify image size attribute
13+
*/
14+
15+
export function preload(images, size) {
16+
if (typeof images === 'string') {
17+
images = [images];
18+
}
19+
20+
for (let i = 0; i < images.length; i++) {
21+
const image = images[i];
22+
this.loadImage(this.getSizedImageUrl(image, size));
23+
}
24+
}
25+
26+
/**
27+
* Loads and caches an image in the browsers cache.
28+
* @param {string} path - An image url
29+
*/
30+
export function loadImage(path) {
31+
new Image().src = path;
32+
}
33+
34+
/**
35+
* Find the Shopify image attribute size
36+
*
37+
* @param {string} src
38+
* @returns {null}
39+
*/
40+
export function imageSize(src) {
41+
const match = src.match(
42+
/.+_((?:pico|icon|thumb|small|compact|medium|large|grande)|\d{1,4}x\d{0,4}|x\d{1,4})[_\.@]/
43+
);
44+
45+
if (match) {
46+
return match[1];
47+
} else {
48+
return null;
49+
}
50+
}
51+
52+
/**
53+
* Adds a Shopify size attribute to a URL
54+
*
55+
* @param src
56+
* @param size
57+
* @returns {*}
58+
*/
59+
export function getSizedImageUrl(src, size) {
60+
if (size === null) {
61+
return src;
62+
}
63+
64+
if (size === 'master') {
65+
return this.removeProtocol(src);
66+
}
67+
68+
const match = src.match(/\.(jpg|jpeg|gif|png|bmp|bitmap|tiff|tif)(\?v=\d+)?$/i);
69+
70+
if (match) {
71+
const prefix = src.split(match[0]);
72+
const suffix = match[0];
73+
74+
return this.removeProtocol(`${prefix[0]}_${size}${suffix}`);
75+
} else {
76+
return null;
77+
}
78+
}
79+
80+
export function removeProtocol(path) {
81+
return path.replace(/http(s)?:/, '');
82+
}

‎packages/theme-images/package.json

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"name": "@shopify/theme-images",
3+
"version": "1.0.0-alpha.1",
4+
"description":
5+
"A library that helps with basic image operations within Shopify Themes",
6+
"main": "images.js",
7+
"repository": {
8+
"type": "git",
9+
"url": "git+https://github.com/Shopify/theme-scripts.git"
10+
},
11+
"keywords": ["slate"],
12+
"author": "Shopify Inc.",
13+
"license": "MIT",
14+
"bugs": {
15+
"url": "https://github.com/Shopify/theme-scripts/issues"
16+
},
17+
"homepage": "https://github.com/Shopify/theme-scripts#readme"
18+
}

‎packages/theme-product/package.json

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"name": "@shopify/theme-product",
3+
"version": "1.0.0-alpha.1",
4+
"description":
5+
"A library that helps developers work with the Product object within Shopify Themes",
6+
"main": "product.js",
7+
"repository": {
8+
"type": "git",
9+
"url": "git+https://github.com/Shopify/theme-scripts.git"
10+
},
11+
"keywords": ["slate"],
12+
"author": "Shopify Inc.",
13+
"license": "MIT",
14+
"bugs": {
15+
"url": "https://github.com/Shopify/theme-scripts/issues"
16+
},
17+
"homepage": "https://github.com/Shopify/theme-scripts#readme",
18+
"peerDependencies": {
19+
"jquery": "3.x",
20+
"lodash-es": "4.x"
21+
}
22+
}

‎packages/theme-product/product.js

+80
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
import find from 'lodash-es/find';
2+
import findIndex from 'lodash-es/findIndex';
3+
import isArray from 'lodash-es/isArray';
4+
5+
export function validate(product) {
6+
if (typeof product !== 'object' || typeof product.id !== 'number') {
7+
throw Error('Please pass a valid Product object to the Product Controller');
8+
}
9+
10+
return $.extend({}, product);
11+
}
12+
13+
export function getVariant(product, value) {
14+
let variant;
15+
16+
if (typeof value === 'string' || typeof value === 'number') {
17+
// If value is an id
18+
variant = this._getVariantFromId(product, value);
19+
} else if (typeof value === 'object' && typeof value.id === 'number') {
20+
// If value is a variant object containing an id key
21+
variant = this._getVariantFromId(product, value.id);
22+
} else if (isArray(value)) {
23+
// If value is an array of options
24+
if (typeof value[0] === 'object') {
25+
// If value is a collection of options with name and value keys
26+
variant = this._getVariantFromOptionCollection(product, value);
27+
} else {
28+
// If value is an array of option values, ordered by index of array
29+
variant = this._getVariantFromOptionArray(product, value);
30+
}
31+
}
32+
33+
return variant;
34+
}
35+
36+
export function optionArrayFromOptionCollection(product, collection) {
37+
const optionArray = [];
38+
39+
collection.forEach((option) => {
40+
let index;
41+
42+
if (typeof option.name !== 'string') {
43+
throw Error(
44+
`Invalid value type passed for name of option ${
45+
index
46+
}. Value should be string.`
47+
);
48+
}
49+
50+
index = findIndex(product.options, (name) => {
51+
return name.toLowerCase() === option.name.toLowerCase();
52+
});
53+
54+
if (index === -1) {
55+
throw Error(`Invalid option name, ${option.name}`);
56+
}
57+
58+
optionArray[index] = option.value;
59+
});
60+
61+
return optionArray;
62+
}
63+
64+
function _getVariantFromId(product, id) {
65+
return find(product.variants, {id});
66+
}
67+
68+
function _getVariantFromOptionCollection(product, collection, closest) {
69+
const optionArray = this.optionArrayFromOptionCollection(product, collection);
70+
71+
return this._getVariantFromOptionArray(product, optionArray, closest);
72+
}
73+
74+
function _getVariantFromOptionArray(product, options) {
75+
return find(product.variants, (variant) => {
76+
return options.every((option, index) => {
77+
return variant.options[index] === option;
78+
});
79+
});
80+
}

‎packages/theme-rte/package.json

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"name": "@shopify/theme-rte",
3+
"version": "1.0.0-alpha.1",
4+
"description":
5+
"A library that helps developers work with the RTE sections in Shopify Themes",
6+
"main": "rte.js",
7+
"repository": {
8+
"type": "git",
9+
"url": "git+https://github.com/Shopify/theme-scripts.git"
10+
},
11+
"keywords": ["slate"],
12+
"author": "Shopify Inc.",
13+
"license": "MIT",
14+
"bugs": {
15+
"url": "https://github.com/Shopify/theme-scripts/issues"
16+
},
17+
"homepage": "https://github.com/Shopify/theme-scripts#readme",
18+
"peerDependencies": {
19+
"jquery": "3.x"
20+
}
21+
}

‎packages/theme-rte/rte.js

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/**
2+
* Rich Text Editor
3+
* -----------------------------------------------------------------------------
4+
* Wrap iframes and tables in div tags to force responsive/scrollable layout.
5+
*
6+
*/
7+
8+
import $ from 'jquery';
9+
10+
/**
11+
* Wrap tables in a container div to make them scrollable when needed
12+
*
13+
* @param {object} options - Options to be used
14+
* @param {jquery} options.$tables - jquery object(s) of the table(s) to wrap
15+
* @param {string} options.tableWrapperClass - table wrapper class name
16+
*/
17+
export function wrapTable(options) {
18+
const tableWrapperClass =
19+
typeof options.tableWrapperClass === 'undefined'
20+
? ''
21+
: options.tableWrapperClass;
22+
23+
options.$tables.wrap(`<div class="${tableWrapperClass}"></div>`);
24+
}
25+
26+
/**
27+
* Wrap iframes in a container div to make them responsive
28+
*
29+
* @param {object} options - Options to be used
30+
* @param {jquery} options.$iframes - jquery object(s) of the iframe(s) to wrap
31+
* @param {string} options.iframeWrapperClass - class name used on the wrapping div
32+
*/
33+
export function wrapIframe(options) {
34+
const iframeWrapperClass =
35+
typeof options.iframeWrapperClass === 'undefined'
36+
? ''
37+
: options.iframeWrapperClass;
38+
39+
options.$iframes.each(function() {
40+
// Add wrapper to make video responsive
41+
$(this).wrap(`<div class="${iframeWrapperClass}"></div>`);
42+
43+
// Re-set the src attribute on each iframe after page load
44+
// for Chrome's "incorrect iFrame content on 'back'" bug.
45+
// https://code.google.com/p/chromium/issues/detail?id=395791
46+
// Need to specifically target video and admin bar
47+
this.src = this.src;
48+
});
49+
}

‎packages/theme-sections/package.json

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"name": "@shopify/theme-sections",
3+
"version": "1.0.0-alpha.1",
4+
"description":
5+
"A framework that helps developers build Shopify Theme sections that play well with the Shopify Theme Editor",
6+
"main": "sections.js",
7+
"repository": {
8+
"type": "git",
9+
"url": "git+https://github.com/Shopify/theme-scripts.git"
10+
},
11+
"keywords": ["slate"],
12+
"author": "Shopify Inc.",
13+
"license": "MIT",
14+
"bugs": {
15+
"url": "https://github.com/Shopify/theme-scripts/issues"
16+
},
17+
"homepage": "https://github.com/Shopify/theme-scripts#readme",
18+
"peerDependencies": {
19+
"jquery": "3.x",
20+
"lodash-es": "4.x"
21+
}
22+
}

‎packages/theme-sections/sections.js

+468
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)
This repository has been archived.